package org.jeecg.modules.chg.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang.math.RandomUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.system.vo.SysVarModel;
import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.config.mybatis.TenantContext;
import org.jeecg.modules.arc.entity.ArcAccount;
import org.jeecg.modules.arc.entity.ArcAccountMeter;
import org.jeecg.modules.arc.entity.BasePeriod;
import org.jeecg.modules.arc.service.IArcAccountMeterService;
import org.jeecg.modules.arc.service.IArcAccountService;
import org.jeecg.modules.arc.service.IArcCustomersService;
import org.jeecg.modules.arc.service.IBasePeriodService;
import org.jeecg.modules.arc.vo.ArcAccountCusVO;
import org.jeecg.modules.arc.vo.ArcIndexDataVO;
import org.jeecg.modules.bl.entity.BlExpenses;
import org.jeecg.modules.bl.entity.BlSubExpenses;
import org.jeecg.modules.bl.service.IBlExpensesService;
import org.jeecg.modules.bl.service.IBlSubExpensesService;
import org.jeecg.modules.bv.entity.BvSubVouchers;
import org.jeecg.modules.bv.entity.BvVouchers;
import org.jeecg.modules.bv.service.IBvSubVouchersService;
import org.jeecg.modules.bv.service.IBvVersionsService;
import org.jeecg.modules.bv.service.IBvVouchersService;
import org.jeecg.modules.bv.vo.BvIndexDataVO;
import org.jeecg.modules.chg.entity.*;
import org.jeecg.modules.chg.mapper.ChgFeesMapper;
import org.jeecg.modules.chg.mapper.ChgSubFeesMapper;
import org.jeecg.modules.chg.service.*;
import org.jeecg.modules.chg.vo.*;
import org.jeecg.modules.his.entity.HisArrearExpenses;
import org.jeecg.modules.his.entity.HisArrears;
import org.jeecg.modules.his.entity.HisSubArrear;
import org.jeecg.modules.his.service.IHisArrearExpensesService;
import org.jeecg.modules.his.service.IHisArrearsService;
import org.jeecg.modules.his.service.IHisSubArrearService;
import org.jeecg.modules.his.vo.HisArrearsPage;
import org.jeecg.modules.mr.service.IMrRecordsService;
import org.jeecg.modules.mr.vo.MrIndexDataVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 收费记录
 * @Author: jeecg-boot
 * @Date:   2022-02-21
 * @Version: V1.0
 */
@Service
public class ChgFeesServiceImpl extends ServiceImpl<ChgFeesMapper, ChgFees> implements IChgFeesService {

	@Autowired
	private ChgFeesMapper chgFeesMapper;
	@Autowired
	private ChgSubFeesMapper chgSubFeesMapper;
	@Autowired
	private IBasePeriodService basePeriodService;
	@Autowired
	private IChgFeesService feesService;
	@Autowired
	private IChgSubFeesService subFeesService;
	@Autowired
	private IChgPaymentsService paymentsService;
	@Autowired
	private IChgStoredsService storedsService;
	@Autowired
	private IChgStrikesService strikesService;
	@Autowired
	private IChgArrearsService arrearsService;
	@Autowired
	private IChgSubArrearService subArrearService;
	@Autowired
	private IChgArrearExpensesService chgArrearExpensesService;
	@Autowired
	private IArcAccountService accountService;
	@Autowired
	private IArcCustomersService arcCustomersService;
	@Autowired
	private IArcAccountMeterService arcAccountMeterService;
	@Autowired
	private IMrRecordsService mrRecordsService;
	@Autowired
	private IHisArrearsService hisArrearsService;
	@Autowired
	private IHisSubArrearService hisSubArrearsService;
	@Autowired
	private IHisArrearExpensesService hisArrearExpensesService;

	@Autowired
	private IBvVouchersService bvVouchersService;
	@Autowired
	private IBvVersionsService bvVersionsService;
	@Autowired
	private IBvSubVouchersService subVouchersService;
	@Autowired
	private IBlExpensesService blExpensesService;
	@Autowired
	private IBlSubExpensesService blSubExpensesService;
	@Autowired
	private IChgDerateService chgDerateService;
	@Autowired
	private RedisUtil redisUtil;

	@Autowired
	private ISysBaseAPI baseAPI;


	@Override
	@Transactional
	public void saveMain(ChgFees chgFees, List<ChgSubFees> chgSubFeesList) {
		chgFeesMapper.insert(chgFees);
		if (chgSubFeesList != null && chgSubFeesList.size() > 0) {
			for (ChgSubFees entity : chgSubFeesList) {
				//外键设置
				entity.setChargeId(chgFees.getId());
				chgSubFeesMapper.insert(entity);
			}
		}
	}

	@Override
	@Transactional
	public void updateMain(ChgFees chgFees, List<ChgSubFees> chgSubFeesList) {
		chgFeesMapper.updateById(chgFees);

		//1.先删除子表数据
		chgSubFeesMapper.deleteByMainId(chgFees.getId());

		//2.子表数据重新插入
		if (chgSubFeesList != null && chgSubFeesList.size() > 0) {
			for (ChgSubFees entity : chgSubFeesList) {
				//外键设置
				entity.setChargeId(chgFees.getId());
				chgSubFeesMapper.insert(entity);
			}
		}
	}

	@Override
	@Transactional
	public void delMain(String id) {
		chgSubFeesMapper.deleteByMainId(id);
		chgFeesMapper.deleteById(id);
	}

	@Override
	@Transactional
	public void delBatchMain(Collection<? extends Serializable> idList) {
		for (Serializable id : idList) {
			chgSubFeesMapper.deleteByMainId(id.toString());
			chgFeesMapper.deleteById(id);
		}
	}

	/**
	 * 窗口缴费
	 */
	@Override
	@Transactional
	public Result<?> charge(ChgChargeFeeVo chargeFeeVo) {

		/**
		 * 缴费记录只跟收支有关
		 *
		 * accountId 缴费账户ID
		 * arrear[] arrearId 欠费ID
		 *
		 * feeChargeType 收费方式 收费类型1,全部收费,2余额预存（收费剩下）3部分收取（不支持）
		 * feePayType 支付方式 （现金、预存扣款、预存开票、POS、微信、支付宝。。。）
		 * feeWholeType 整收方式 1实收（先扣余额），2不扣余额实收
		 * feeTargetType 收费目的（收费、预存）
		 * feePayWay 支付方式
		 *
		 * recivedMoney 实收金额
		 * payableMoney 应收金额
		 *
		 * 打印方式
		 * 票据类型
		 *
		 */

		//chargeObj = (JSONObject) JSONObject.parse(JSON.toJSONString(chargeObj));

		//JSONArray arrearArray = chargeObj.getJSONArray("arrear");
		//String[] arrearStr = (String[]) arrearArray.toArray();

		long b=System.currentTimeMillis();

		LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
		List<ChgArrears> chgArrearLs=null;
		if(null != chargeFeeVo.getArrearIds() && chargeFeeVo.getArrearIds().size()>0){
			chgArrearLs= arrearsService.list(new LambdaQueryWrapper<ChgArrears>()
					.in(ChgArrears::getId, chargeFeeVo.getArrearIds())
					.orderByAsc(ChgArrears::getReadMonth));
			//chgArrearLs = arrearsService.listByIds(chargeFeeVo.getArrearIds());

			for (ChgArrears chgArrearL : chgArrearLs) {
				//查验是否跳月缴费的
				int count = arrearsService.count(new LambdaQueryWrapper<ChgArrears>()
						.eq(ChgArrears::getDelFlag, 0)
						.eq(ChgArrears::getCusId,chgArrearL.getCusId())
						.lt(ChgArrears::getReadMonth, chgArrearL.getReadMonth())
						.notIn(ChgArrears::getId, chargeFeeVo.getArrearIds())
						.orderByAsc(ChgArrears::getReadMonth));
				if (count > 0) {
					//存在跳月收费
					return Result.error("不允许跳月收费");
				}
			}
		}

		BasePeriod basePeriod = basePeriodService.getOne(
				new LambdaQueryWrapper<BasePeriod>().eq(BasePeriod::getIsUsed, 1));

		//缴费账户
		ArcAccount arcAccount = accountService.getById(chargeFeeVo.getId());
		if (null == arcAccount) {
			//缴费账户不存在
			return Result.error("缴费账户不存在");
		}
		//账户余额
		BigDecimal balance = arcAccount.getBalance();
		BigDecimal pre_balance = arcAccount.getBalance();
		//应收金额
		BigDecimal payableMoney = chargeFeeVo.getReceFee();
		//实缴
		BigDecimal realFee = chargeFeeVo.getRealFee();
		//实收金额-付款
		BigDecimal recivedMoney = chargeFeeVo.getPayFee();
		if (null == recivedMoney) {
			recivedMoney = new BigDecimal(0.0);
		}
		//当前结余
		BigDecimal currMoney =new BigDecimal(0.0);
		//总余额=上次余额+实收-应收-找零
		BigDecimal totalMoney = balance.add(recivedMoney).subtract(payableMoney).subtract(chargeFeeVo.getZeroFee());

		//整收方式 1实收（先扣余额），2不扣余额实收
		if ("01".equals(chargeFeeVo.getFeeWholeWay())) {
			BigDecimal subtract = balance.add(recivedMoney).subtract(payableMoney);
			if (subtract.doubleValue() < 0) {
				//支付金额不够
				return Result.error("支付金额不够");
			}
			currMoney=balance.add(recivedMoney).subtract(chargeFeeVo.getZeroFee());
		} else if ("02".equals(chargeFeeVo.getFeeWholeWay())) {
			BigDecimal subtract = recivedMoney.subtract(payableMoney);
			if (subtract.doubleValue() < 0) {
				//支付金额不够
				return Result.error("支付金额不够");
			}
			currMoney=recivedMoney.subtract(chargeFeeVo.getZeroFee());
		}

		//返回
		JSONObject rsObject = new JSONObject();
		//用户收费对应ID
		//JSONObject userFeeIdJson = new JSONObject();

		Set<String> cusSet = new HashSet<>();
		List<ChgSubPayments> subPaymentsList = new ArrayList<>();
		//批次号
		Integer index = 0;
		String batchNo = createBatchNo();

		log.warn("缴费基础数据："+(System.currentTimeMillis()-b)+"毫秒");

		/**1 缴费、缴费明细 */
		ChgPaymentsPage paymentsPage = new ChgPaymentsPage();
		paymentsPage.setAccountId(chargeFeeVo.getId());
		paymentsPage.setAccCode(chargeFeeVo.getAccCode());
		paymentsPage.setAccName(chargeFeeVo.getAccName());
		paymentsPage.setFeeTargetType("1");//收费
		paymentsPage.setFeePayWay(chargeFeeVo.getFeePayWay());//支付方式
		paymentsPage.setFeeTollWay(chargeFeeVo.getFeeTollWay());//收费方式
		paymentsPage.setFeeWholeWay(chargeFeeVo.getFeeWholeWay());//整收方式
		paymentsPage.setBillTypeId(chargeFeeVo.getBillTypeId());//票据类型
		paymentsPage.setFeePrintWay(chargeFeeVo.getFeePrintWay());//打印方式
		paymentsPage.setFinancialDate(DateUtils.formatDate(new Date(), "yyyy-MM-dd HH:mm:ss"));
		paymentsPage.setFinancialMonth(basePeriod.getMonth() );

		paymentsPage.setPayFee(chargeFeeVo.getPayFee());//付款
		paymentsPage.setZeroFee(chargeFeeVo.getZeroFee());//找零
		paymentsPage.setPreMoney(arcAccount.getBalance());//缴费前余额

		//收费方式 是否预存
		if ("02".equals(chargeFeeVo.getFeeTollWay())) {
			//余额预存

			//实收
			if ("01".equals(chargeFeeVo.getFeeWholeWay())) {
				BigDecimal subtract1 = payableMoney.subtract(balance);
				if(subtract1.doubleValue()>= 0){
					paymentsPage.setMoney(subtract1);//本次实收= 应付-余额
					paymentsPage.setUseStoredMoney(balance);//余额不够，先用掉余额的
					balance=new BigDecimal(0.0);
				}else{
					//余额大于应付款
					paymentsPage.setMoney(new BigDecimal(0.0));//本次实收= 余额金额够用，本次不用缴费
					paymentsPage.setUseStoredMoney(payableMoney);//需要实缴的 余额够用，直接实缴
					balance=balance.subtract(payableMoney);
				}

				paymentsPage.setStoredPaymentMoney(totalMoney);//缴费后剩余余额-作为预存后的余额

			} else if ("02".equals(chargeFeeVo.getFeeWholeWay())) {
				//不扣余额
				paymentsPage.setMoney(realFee);//实收 -多余找零
				paymentsPage.setUseStoredMoney(new BigDecimal(0.0));//不用余额缴费

				// 实收-应收-找零=剩余的
				BigDecimal subtract = recivedMoney.subtract(payableMoney).subtract(chargeFeeVo.getZeroFee());

				paymentsPage.setStoredPaymentMoney(subtract);//缴费后剩余余额-作为预存后的余额
			}
		} else {
			//实收
			if ("01".equals(chargeFeeVo.getFeeWholeWay())) {
				BigDecimal subtract1 = payableMoney.subtract(balance);

				if(subtract1.doubleValue()>= 0){
					paymentsPage.setMoney(subtract1);//本次实收= 应付-余额
					paymentsPage.setUseStoredMoney(balance);
					balance=new BigDecimal(0.0);
				}else{
					//余额大于应付款
					paymentsPage.setMoney(new BigDecimal(0.0));//本次实收= 余额金额够用，本次不用缴费
					paymentsPage.setUseStoredMoney(payableMoney);
					balance=balance.subtract(payableMoney);
				}
				paymentsPage.setStoredPaymentMoney(new BigDecimal(0.0));//有剩余需要找零的
			} else if ("02".equals(chargeFeeVo.getFeeWholeWay())) {
				//不扣余额
				paymentsPage.setMoney(realFee);//实收 -多余找零
				paymentsPage.setStoredPaymentMoney(new BigDecimal(0.0));//有剩余需要找零-不再平台体现
			}
		}

		balance=paymentsPage.getStoredPaymentMoney();
		paymentsPage.setPostMoney(totalMoney);//缴费后余额

		//缴费明细-
		ChgSubPayments subPayments = new ChgSubPayments();
		subPayments.setFeePayType(chargeFeeVo.getFeeTollWay());
		subPayments.setMoney(paymentsPage.getMoney());
		subPaymentsList.add(subPayments);

		paymentsPage.setStatus(1);
		paymentsPage.setSerialNo(batchNo);
		paymentsPage.setBatchNo(batchNo);

		paymentsPage.setChgSubPaymentsList(subPaymentsList);

		ChgPayments chgPayments = new ChgPayments();
		BeanUtils.copyProperties(paymentsPage, chgPayments);
		paymentsService.saveMain(chgPayments, paymentsPage.getChgSubPaymentsList());

		index++;
		//余额预存
		ChgStoreds storeds = new ChgStoreds();
		storeds.setAccCode(chargeFeeVo.getAccCode());
		storeds.setAccName(chargeFeeVo.getAccName());
		//storeds.setChargeId(chgFees.getId());
		storeds.setAccountId(arcAccount.getId());
		storeds.setPaymentId(chgPayments.getId());
		storeds.setBatchNo(batchNo + "" + index);
		storeds.setFeeStruckStatus("1");
		if(null != chgArrearLs && chgArrearLs.size()>0){
			storeds.setFeeTargetType("2");///缴费类型 1-收费,2-缴费,3-退费，4预存 5预存扣费
		}else{
			//没有勾选欠费过来，就默认充值预存
			storeds.setFeeTargetType("4");///缴费类型 1-收费,2-缴费,3-退费，4预存 5预存扣费
		}
		storeds.setFinancialDate(paymentsPage.getFinancialDate());
		storeds.setFinancialMonth(paymentsPage.getFinancialMonth());
		storeds.setStatus(1);

		storeds.setPreBalance(arcAccount.getBalance());
		storeds.setMoney(recivedMoney.subtract(chargeFeeVo.getZeroFee()));//付款-找零
		storeds.setPostBalance(storeds.getPreBalance().add(storeds.getMoney()));//余额+本次缴费

		storeds.setChargeTime(DateUtils.getDate("yyyy-MM-dd HH:mm:ss"));
		storeds.setCashierId(sysUser.getUsername());
		storedsService.save(storeds);

		log.warn("缴费处理："+(System.currentTimeMillis()-b)+"毫秒");

		index++;
		if(null != chgArrearLs && chgArrearLs.size()>0){
			for (ChgArrears chgArrear : chgArrearLs) {
				/**2 收费、收费明细 */
				ChgFeesPage chgFeesPage = new ChgFeesPage();
				ArrayList<ChgSubFees> chgSubFeesLs = new ArrayList<>();
				/**历史欠费明细*/
				ArrayList<HisSubArrear> chgHisSubFeesLs = new ArrayList<>();

				//欠费明细
				List<ChgSubArrear> subArrearList = subArrearService.selectByMainId(chgArrear.getId());
				for (ChgSubArrear subArrear : subArrearList) {
					ChgSubFees subFees = new ChgSubFees();
					subFees.setNatureId(subArrear.getNatureId());
					subFees.setPriceId(subArrear.getPriceId());
					subFees.setPrice(subArrear.getPrice());
					subFees.setItemCode(subArrear.getItemCode());
					subFees.setSubExpenseId(subArrear.getSubExpenseId());
					subFees.setAmount(subArrear.getAmount());
					subFees.setTierNo(subArrear.getTierNo());
					subFees.setVatMoney(subArrear.getVatMoney());
					subFees.setDerateMoney(subArrear.getDerateMoney());
					subFees.setMoney(subArrear.getArrearMoney());
					chgSubFeesLs.add(subFees);

					HisSubArrear hisSubArrear = new HisSubArrear();
					BeanUtils.copyProperties(subArrear, hisSubArrear);
					hisSubArrear.setId(null);
					chgHisSubFeesLs.add(hisSubArrear);
				}

				chgFeesPage.setBookId(chgArrear.getBookId());
				chgFeesPage.setBeginScale(chgArrear.getBeginScale());
				chgFeesPage.setEndScale(chgArrear.getEndScale());
				chgFeesPage.setReadMonth(chgArrear.getReadMonth());
				chgFeesPage.setReaderId(chgArrear.getReaderId());
				chgFeesPage.setAmount(chgArrear.getArrearAmount());
				chgFeesPage.setCusId(chgArrear.getCusId());
				chgFeesPage.setCusName(chgArrear.getCusName());
				chgFeesPage.setFeeChargeType(chargeFeeVo.getFeeTollWay());
				chgFeesPage.setFeePayWay(paymentsPage.getFeePayWay());//支付方式
				chgFeesPage.setFeeStruckStatus(1);
				chgFeesPage.setFinancialDate(paymentsPage.getFinancialDate());
				chgFeesPage.setFinancialMonth(paymentsPage.getFinancialMonth());

				chgFeesPage.setTotalMoney(chgArrear.getTotalMoney());//水费
				chgFeesPage.setPenalty(chgArrear.getPenalty());//违约金
				chgFeesPage.setWuMoney(chgArrear.getWuMoney());//污水
				chgFeesPage.setAlienMoney(chgArrear.getAlienMoney());//杂项费用
				chgFeesPage.setJiMoney(chgArrear.getJiMoney());//季加
				chgFeesPage.setJyMoney(chgArrear.getJyMoney());//二加压
				chgFeesPage.setLjMoney(chgArrear.getLjMoney());//垃圾费
				chgFeesPage.setDerateMoney(chgArrear.getDerateMoney());// 减免金额

				chgFeesPage.setPreBalance(pre_balance);//真实，本次缴费前的
				//实欠=欠费-已收
				BigDecimal realArrearMoney = chgArrear.getArrearMoney().subtract(chgArrear.getRecivedMoney());
				chgFeesPage.setMoney(realArrearMoney);//该笔欠费金额

				/** 先缴费充值，后收费，都是从预存余额扣除*/
				chgFeesPage.setRecivedMoney(new BigDecimal(0.0));//实收=0
				chgFeesPage.setStoredPaymentMoney(chgFeesPage.getMoney());//用预存余额缴费的,

				//本次结余
				currMoney = currMoney.subtract(chgFeesPage.getMoney());
				chgFeesPage.setPostBalance(currMoney);
				pre_balance=currMoney;

				////整收方式 1实收（先扣余额），2不扣余额实收
				//if ("01".equals(chargeFeeVo.getFeeWholeWay())) {
				//	chgFeesPage.setRecivedMoney(chgFeesPage.getMoney());//实收=该笔欠费金额
				//
				//	BigDecimal subtract1 = chgFeesPage.getMoney().subtract(currMoney);
				//
				//	if(subtract1.doubleValue()> 0){
				//		chgFeesPage.setStoredPaymentMoney(balance);//用预存余额缴费的
				//	}else{
				//		//余额大于应付款
				//		chgFeesPage.setStoredPaymentMoney(chgFeesPage.getMoney());//用预存余额缴费的
				//	}
				//
				//	//本次结余
				//	currMoney = currMoney.subtract(chgFeesPage.getMoney());
				//	chgFeesPage.setPostBalance(currMoney);//本次结余
				//
				//	//balance = currMoney;
				//} else if ("02".equals(chargeFeeVo.getFeeWholeWay())) {
				//	chgFeesPage.setRecivedMoney(chgFeesPage.getMoney());//实收金额付款=该笔欠费金额
				//	chgFeesPage.setStoredPaymentMoney(new BigDecimal(0.0));//用预存余额缴费的
				//
				//	//本次结余
				//	currMoney = currMoney.subtract(chgFeesPage.getMoney());
				//	chgFeesPage.setPostBalance(currMoney);//本次结余
				//}

				chgFeesPage.setRemark("扣费");
				chgFeesPage.setStatus(1);
				chgFeesPage.setPaymentId(chgPayments.getId());
				chgFeesPage.setBatchNo(batchNo + "" + index);
				chgFeesPage.setChgSubFeesList(chgSubFeesLs);

				ChgFees chgFees = new ChgFees();
				BeanUtils.copyProperties(chgFeesPage, chgFees);
				feesService.saveMain(chgFees, chgFeesPage.getChgSubFeesList());

				/**3余额记录*/
				if (chgFeesPage.getMoney().doubleValue() > 0) {
					ChgStoreds storedFee = new ChgStoreds();
					storedFee.setAccCode(chargeFeeVo.getAccCode());
					storedFee.setAccName(chargeFeeVo.getAccName());
					storedFee.setAccountId(paymentsPage.getAccountId());
					storedFee.setChargeId(chgFees.getId());
					storedFee.setPaymentId(chgPayments.getId());
					storedFee.setBatchNo(batchNo + "" + index);
					storedFee.setFeeStruckStatus("1");
					storedFee.setFeeTargetType("1");//缴费类型 1-收费,2-缴费,3-退费，4预存 5预存扣费
					storedFee.setFinancialDate(paymentsPage.getFinancialDate());
					storedFee.setFinancialMonth(paymentsPage.getFinancialMonth());
					storedFee.setStatus(1);

					storedFee.setPreBalance(chgFeesPage.getPreBalance());
					storedFee.setMoney(chgFeesPage.getMoney());
					storedFee.setPostBalance(chgFeesPage.getPostBalance());

					storedFee.setChargeTime(DateUtils.getDate("yyyy-MM-dd HH:mm:ss"));
					storedFee.setCashierId(sysUser.getUsername());
					storedsService.save(storedFee);
				}
				/**4.对应的欠费记录删除，欠费历史增加*/

				HisArrearsPage hisArrearsPage = new HisArrearsPage();
				BeanUtils.copyProperties(chgArrear, hisArrearsPage);
				hisArrearsPage.setId(null);
				hisArrearsPage.setHisSubArrearList(chgHisSubFeesLs);

				HisArrears hisArrears = new HisArrears();
				BeanUtils.copyProperties(hisArrearsPage, hisArrears);
				hisArrears.setFeeId(chgFees.getId());
				//原欠费ID
				hisArrears.setOldArrId(chgArrear.getId());
				hisArrearsService.saveMain(hisArrears, hisArrearsPage.getHisSubArrearList());

				//List<ChgArrearExpenses> arrearExpensesList = chgArrearExpensesService.list(
				//		new LambdaQueryWrapper<ChgArrearExpenses>()
				//				.eq(ChgArrearExpenses::getArrearId, chgArrear.getId())
				//				.eq(ChgArrearExpenses::getDelFlag, 0));
				//
				//if (null != arrearExpensesList && arrearExpensesList.size() > 0) {
				//	for (ChgArrearExpenses arrearExpenses : arrearExpensesList) {
				//		HisArrearExpenses harrearExpenses = new HisArrearExpenses();
				//		BeanUtils.copyProperties(arrearExpenses, harrearExpenses);
				//		harrearExpenses.setId(null);
				//		hisArrearExpensesService.save(harrearExpenses);
				//	}
				//}

				arrearsService.delAlienSubByMainId(chgArrear.getId());
				arrearsService.delMain(chgArrear.getId());
			}

			log.warn("欠费处理："+(System.currentTimeMillis()-b)+"毫秒");

			///**设置首页数据动态更新*/
			new Thread(new Runnable() {
				@Override
				public void run() {
					try {
						indexData(null,null);
					} catch (Exception e) {
						e.printStackTrace();
					} finally {
						log.warn("首页数据动态更新");
					}
				}
			}).start();
		}
		/**5.缴费账户余额变化*/

		//余额需要预存的
		if (paymentsPage.getStoredPaymentMoney().doubleValue() > 0) {
			//还有剩余，是否预存  否则找零
			index++;
			//余额预存

			if(null != chgArrearLs && chgArrearLs.size()>0) {

				ChgStoreds chgStoreds = new ChgStoreds();
				chgStoreds.setAccCode(chargeFeeVo.getAccCode());
				chgStoreds.setAccName(chargeFeeVo.getAccName());
				//storeds.setChargeId(chgFees.getId());
				chgStoreds.setAccountId(arcAccount.getId());
				chgStoreds.setPaymentId(chgPayments.getId());
				chgStoreds.setBatchNo(batchNo + "" + index);
				chgStoreds.setFeeStruckStatus("1");
				chgStoreds.setFeeTargetType("4");///缴费类型 1-收费,2-缴费,3-退费，4预存 5预存扣费
				chgStoreds.setFinancialDate(DateUtils.formatDate());
				chgStoreds.setFinancialMonth(basePeriod.getMonth());
				chgStoreds.setStatus(1);

				chgStoreds.setPreBalance(arcAccount.getBalance());
				chgStoreds.setMoney(paymentsPage.getStoredPaymentMoney());

				if ("01".equals(chargeFeeVo.getFeeWholeWay())) {
					//实收 上次余额一起参与进来收费了
					chgStoreds.setPostBalance(paymentsPage.getStoredPaymentMoney());
				} else if ("02".equals(chargeFeeVo.getFeeWholeWay())) {
					//不扣余额时，=上次余额+本次剩余
					chgStoreds.setPostBalance(arcAccount.getBalance().add(paymentsPage.getStoredPaymentMoney()));
				}

				chgStoreds.setChargeTime(DateUtils.getDate("yyyy-MM-dd HH:mm:ss"));
				chgStoreds.setCashierId(sysUser.getUsername());
				storedsService.save(chgStoreds);

				/**设置首页数据动态更新 - 预存*/

				new Thread(new Runnable() {
					@Override
					public void run() {
						try {
							indexData(null,null);
						} catch (Exception e) {
							e.printStackTrace();
						} finally {
							log.warn("首页数据动态更新");
						}
					}
				}).start();
			}
			//else{
			//	//没有勾选欠费过来，就是预存，前面已预存过了
			//}

		}

		//实付=付款-找零
		//BigDecimal real = chargeFeeVo.getPayFee().subtract(chargeFeeVo.getZeroFee());

		//是否需要打印收据
		SysVarModel isPrintBill = baseAPI.querySysVar("is_print_bill");//是否打印收据
		if(null == isPrintBill || "0".equals(isPrintBill.getValue() )){
			rsObject.put("isPrintBill", 0);
		}else{
			rsObject.put("isPrintBill", 1);
		}

		accountService.update(new LambdaUpdateWrapper<ArcAccount>()
				.set(ArcAccount::getBalance, totalMoney)
				.eq(ArcAccount::getId, arcAccount.getId()));

		rsObject.put("paymentId", chgPayments.getId());
		//rsObject.put("userFee", userFeeIdJson);
		rsObject.put("accountId", arcAccount.getId());

		log.warn("收费总时长："+(System.currentTimeMillis()-b)+"毫秒");
		return Result.OK(rsObject);
		/***6票据*/

		//String billTypeId = chargeObj.getString("billTypeId");
		//String feePrintWay = chargeObj.getString("feePrintWay");
		//BvVersions currentVersion = bvVersionsService.getCurrentVersion(billTypeId);
		//
		//BvVouchers nextVouchers = bvVouchersService.getNextVouchers(
		//		chargeObj.getString("billTypeId"), currentVersion.getId());
		//
		//nextVouchers.setBillStatusId("02");
		//nextVouchers.setFinancialDate();
	}

	/**微信预存-微信下单-预支付的*/
	@Override
	public ChgPayments storedPreCharge(ChgChargeFeeVo chargeFeeVo,JSONObject orderObj){
		BasePeriod basePeriod = basePeriodService.getOne(
				new LambdaQueryWrapper<BasePeriod>().eq(BasePeriod::getIsUsed, 1));

		//缴费账户
		ArcAccount arcAccount = accountService.getById(chargeFeeVo.getId());
		if (null == arcAccount) {
			//缴费账户不存在
			throw new JeecgBootException("缴费账户不存在");
		}

		/**1 缴费、缴费明细 */
		ChgPaymentsPage paymentsPage = new ChgPaymentsPage();
		paymentsPage.setAccountId(chargeFeeVo.getId());
		paymentsPage.setAccCode(chargeFeeVo.getAccCode());
		paymentsPage.setAccName(chargeFeeVo.getAccName());
		paymentsPage.setFeeTargetType("4");//预存
		paymentsPage.setFeePayWay(chargeFeeVo.getFeePayWay());//支付方式 3微信5农行
		paymentsPage.setFeeTollWay(chargeFeeVo.getFeeTollWay());//收费方式 3余额预存（收费剩下）
		paymentsPage.setFeeWholeWay(chargeFeeVo.getFeeWholeWay());//整收方式 实收
		//paymentsPage.setBillTypeId(chargeFeeVo.getBillTypeId());//票据类型
		//paymentsPage.setFeePrintWay(chargeFeeVo.getFeePrintWay());//打印方式
		paymentsPage.setFinancialDate(DateUtils.formatDate(new Date(), "yyyy-MM-dd HH:mm:ss"));
		paymentsPage.setFinancialMonth(basePeriod.getMonth() );
		paymentsPage.setArrearsIds(null != orderObj.get("arrearIds") ? orderObj.get("arrearIds").toString() : null);

		paymentsPage.setPreMoney(arcAccount.getBalance());//缴费前余额
		paymentsPage.setPayFee(chargeFeeVo.getPayFee());//付款
		paymentsPage.setZeroFee(chargeFeeVo.getZeroFee());//找零

		String s = orderObj.getString("createBy");
		paymentsPage.setCreateBy(s);

		paymentsPage.setMoney(chargeFeeVo.getPayFee());//付款
		paymentsPage.setPostMoney(arcAccount.getBalance().add(chargeFeeVo.getPayFee()));//缴费后余额

		paymentsPage.setUseStoredMoney(new BigDecimal(0).setScale(2,BigDecimal.ROUND_HALF_UP));
		List<ChgSubPayments> subPaymentsList = new ArrayList<>();
		//缴费明细-
		ChgSubPayments subPayments = new ChgSubPayments();
		subPayments.setFeePayType(chargeFeeVo.getFeeTollWay());
		subPayments.setMoney(paymentsPage.getMoney());
		subPaymentsList.add(subPayments);

		String batchNo = createBatchNo();
		paymentsPage.setStatus(0);//预充
		//paymentsPage.setSerialNo(batchNo);
		paymentsPage.setBatchNo(batchNo);

		paymentsPage.setChgSubPaymentsList(subPaymentsList);

		ChgPayments chgPayments = new ChgPayments();
		BeanUtils.copyProperties(paymentsPage, chgPayments);
		paymentsService.saveMain(chgPayments, paymentsPage.getChgSubPaymentsList());
		return chgPayments;
	}

	/**
	 * 微信缴费成功-处理
	 */
	@Override
	@Transactional
	public Result<?> mpCharge(ChgChargeFeeVo chargeFeeVo, ChgPayments chgPayments, ArrayList arrearIds) {

		/**
		 * 缴费记录只跟收支有关
		 *
		 * accountId 缴费账户ID
		 * arrear[] arrearId 欠费ID
		 *
		 * feeChargeType 收费方式 收费类型1,全部收费,2余额预存（收费剩下）3部分收取（不支持）
		 * feePayType 支付方式 （现金、预存扣款、预存开票、POS、微信、支付宝。。。）
		 * feeWholeType 整收方式 1实收（先扣余额），2不扣余额实收
		 * feeTargetType 收费目的（收费、预存）
		 * feePayWay 支付方式
		 *
		 * recivedMoney
		 * payableMoney 应收金额
		 *
		 * 打印方式
		 * 票据类型
		 *
		 */

		//chargeObj = (JSONObject) JSONObject.parse(JSON.toJSONString(chargeObj));

		//JSONArray arrearArray = chargeObj.getJSONArray("arrear");
		//String[] arrearStr = (String[]) arrearArray.toArray();
		LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();

		BasePeriod basePeriod = basePeriodService.getOne(
				new LambdaQueryWrapper<BasePeriod>().eq(BasePeriod::getIsUsed, 1));

		//缴费账户
		ArcAccount arcAccount = accountService.getById(chargeFeeVo.getId());
		if (null == arcAccount) {
			//缴费账户不存在
			return Result.error("缴费账户不存在");
		}

		List<ChgArrears> chgArrearLs=null;
		BigDecimal arrearMoney =new BigDecimal(0.0);
		if(null == arrearIds) {
			//预缴

		}else{
			chgArrearLs= arrearsService.list(new LambdaQueryWrapper<ChgArrears>()
					.in(ChgArrears::getId, arrearIds)
					.orderByAsc(ChgArrears::getReadMonth));
//			chgArrearLs= arrearsService.listByIds(arrearIds);
			if(null == chargeFeeVo.getReceFee() ){
				if(null != chgArrearLs && chgArrearLs.size()>0){
					for (ChgArrears arrears : chgArrearLs) {
						arrearMoney = arrearMoney.add(arrears.getArrearMoney().subtract(arrears.getRecivedMoney())).setScale(2,BigDecimal.ROUND_HALF_UP);
					}
				}
			}
		}

		//账户余额
		BigDecimal balance = arcAccount.getBalance();
		BigDecimal pre_balance = arcAccount.getBalance();
		//应收金额
		BigDecimal payableMoney = null != chargeFeeVo.getReceFee() ? chargeFeeVo.getReceFee().setScale(2,BigDecimal.ROUND_HALF_UP) : arrearMoney.setScale(2,BigDecimal.ROUND_HALF_UP);
		//实缴:应收-余额
		BigDecimal realFee =  chargeFeeVo.getRealFee();
		//实收金额-付款金额
		BigDecimal recivedMoney = chgPayments.getPayFee();
		if (null == recivedMoney) {
			recivedMoney = new BigDecimal(0.0);
		}

		chargeFeeVo.setFeeWholeWay("01");
		//当前结余
		BigDecimal currMoney =new BigDecimal(0.0);
		//总余额=上次余额+实收-应收-找零
//		BigDecimal totalMoney = balance.add(recivedMoney).subtract(payableMoney).subtract(chargeFeeVo.getZeroFee());
		BigDecimal totalMoney = balance.add(recivedMoney).subtract(payableMoney).setScale(2,BigDecimal.ROUND_HALF_UP);

		//整收方式 1实收（先扣余额），2不扣余额实收
//		if ("01".equals(chargeFeeVo.getFeeWholeWay())) {
			BigDecimal subtract = balance.add(recivedMoney).subtract(payableMoney).setScale(2,BigDecimal.ROUND_HALF_UP);
			if (subtract.doubleValue() < 0) {
				//支付金额不够
				System.out.println(subtract.doubleValue());
				System.out.println("支付金额不够");
				return Result.error("支付金额不够");
			}
//			currMoney=balance.add(recivedMoney).subtract(chargeFeeVo.getZeroFee());
			currMoney=balance.add(recivedMoney);
//		}

		//返回
		JSONObject rsObject = new JSONObject();
		//用户收费对应ID
		//JSONObject userFeeIdJson = new JSONObject();

		Set<String> cusSet = new HashSet<>();
		//批次号
		Integer index = 0;
		String batchNo = chgPayments.getBatchNo();

		index++;
		//余额预存
		ChgStoreds storeds = new ChgStoreds();
		storeds.setAccCode(chgPayments.getAccCode());
		storeds.setAccName(chgPayments.getAccName());
		//storeds.setChargeId(chgFees.getId());
		storeds.setAccountId(arcAccount.getId());
		storeds.setPaymentId(chgPayments.getId());
		storeds.setBatchNo(batchNo + "" + index);
		storeds.setFeeStruckStatus("1");
		//没有勾选欠费过来，就默认充值预存
		if(chargeFeeVo.getReceFee().doubleValue()>0){
			//有欠费
			storeds.setFeeTargetType("2");///缴费类型 1-收费,2-缴费,3-退费，4预存 5预存扣费
		}else{
			storeds.setFeeTargetType("4");///缴费类型 1-收费,2-缴费,3-退费，4预存 5预存扣费
		}

		storeds.setFinancialDate(chgPayments.getFinancialDate());
		storeds.setFinancialMonth(chgPayments.getFinancialMonth());
		storeds.setStatus(1);
		storeds.setPreBalance(arcAccount.getBalance());
//		storeds.setMoney(recivedMoney.subtract(chargeFeeVo.getZeroFee()));//付款-找零
		storeds.setMoney(recivedMoney);//付款-找零
		storeds.setPostBalance(storeds.getPreBalance().add(storeds.getMoney()));//余额+本次缴费

		storeds.setChargeTime(DateUtils.getDate("yyyy-MM-dd HH:mm:ss"));
		storeds.setCashierId(sysUser.getUsername());
		storedsService.save(storeds);

		//核销缴费记录-状态修改
		paymentsService.update(new LambdaUpdateWrapper<ChgPayments>()
				.set(ChgPayments::getStatus,1)
				.set(ChgPayments::getPostMoney,totalMoney)//预缴本次余额修改
				.set(ChgPayments::getTransactionId,chgPayments.getTransactionId())
				.eq(ChgPayments::getId,chgPayments.getId()));


//		if(null !=chgArrearLs && chgArrearLs.size()>0 ){


		//校验余额，
//		List<ChgArrears> chgArrearLs= arrearsService.listByIds(arrearIds);
		index++;
		if(null != chgArrearLs && chgArrearLs.size()>0){
			for (ChgArrears chgArrear : chgArrearLs) {
				/**2 收费、收费明细 */
				ChgFeesPage chgFeesPage = new ChgFeesPage();
				ArrayList<ChgSubFees> chgSubFeesLs = new ArrayList<>();
				/**历史欠费明细*/
				ArrayList<HisSubArrear> chgHisSubFeesLs = new ArrayList<>();

				//欠费明细
				List<ChgSubArrear> subArrearList = subArrearService.selectByMainId(chgArrear.getId());
				for (ChgSubArrear subArrear : subArrearList) {
					ChgSubFees subFees = new ChgSubFees();
					subFees.setNatureId(subArrear.getNatureId());
					subFees.setPriceId(subArrear.getPriceId());
					subFees.setPrice(subArrear.getPrice());
					subFees.setItemCode(subArrear.getItemCode());
					subFees.setSubExpenseId(subArrear.getSubExpenseId());
					subFees.setAmount(subArrear.getAmount());
					subFees.setTierNo(subArrear.getTierNo());
					subFees.setVatMoney(subArrear.getVatMoney());
					subFees.setMoney(subArrear.getArrearMoney());
					subFees.setDerateMoney(subArrear.getDerateMoney());
					chgSubFeesLs.add(subFees);

					HisSubArrear hisSubArrear = new HisSubArrear();
					BeanUtils.copyProperties(subArrear, hisSubArrear);
					hisSubArrear.setId(null);
					chgHisSubFeesLs.add(hisSubArrear);
				}

				chgFeesPage.setBookId(chgArrear.getBookId());
				chgFeesPage.setBeginScale(chgArrear.getBeginScale());
				chgFeesPage.setEndScale(chgArrear.getEndScale());
				chgFeesPage.setReadMonth(chgArrear.getReadMonth());
				chgFeesPage.setReaderId(chgArrear.getReaderId());
				chgFeesPage.setAmount(chgArrear.getArrearAmount());
				chgFeesPage.setCusId(chgArrear.getCusId());
				chgFeesPage.setCusName(chgArrear.getCusName());
				chgFeesPage.setFeeChargeType("3");
				chgFeesPage.setFeePayWay(chgPayments.getFeePayWay());//支付方式
				chgFeesPage.setFeeStruckStatus(1);
				chgFeesPage.setFinancialDate(chgPayments.getFinancialDate());
				chgFeesPage.setFinancialMonth(chgPayments.getFinancialMonth());

				chgFeesPage.setTotalMoney(chgArrear.getTotalMoney());//水费
				chgFeesPage.setPenalty(chgArrear.getPenalty());//违约金
				chgFeesPage.setWuMoney(chgArrear.getWuMoney());//污水
				chgFeesPage.setAlienMoney(chgArrear.getAlienMoney());//杂项费用
				chgFeesPage.setJiMoney(chgArrear.getJiMoney());//季加
				chgFeesPage.setJyMoney(chgArrear.getJyMoney());//二加压
				chgFeesPage.setLjMoney(chgArrear.getLjMoney());//垃圾费
				chgFeesPage.setDerateMoney(chgArrear.getDerateMoney());// 减免费用

				chgFeesPage.setPreBalance(pre_balance);//上次余额=本次缴费前的
				//实欠=欠费-已收
				BigDecimal realArrearMoney = chgArrear.getArrearMoney().subtract(chgArrear.getRecivedMoney());
				chgFeesPage.setMoney(realArrearMoney);//该笔欠费金额

				/** 先缴费充值，后收费，都是从预存余额扣除*/
				chgFeesPage.setRecivedMoney(new BigDecimal(0.0));//实收=0
				chgFeesPage.setStoredPaymentMoney(chgFeesPage.getMoney().setScale(2,BigDecimal.ROUND_HALF_UP));//用预存余额缴费的,

				//本次结余
				currMoney = currMoney.subtract(chgFeesPage.getMoney()).setScale(2,BigDecimal.ROUND_HALF_UP);
				chgFeesPage.setPostBalance(currMoney);
				pre_balance=currMoney;

				////整收方式 1实收（先扣余额），2不扣余额实收
				//if ("01".equals(chargeFeeVo.getFeeWholeWay())) {
				//	chgFeesPage.setRecivedMoney(chgFeesPage.getMoney());//实收=该笔欠费金额
				//
				//	BigDecimal subtract1 = chgFeesPage.getMoney().subtract(currMoney);
				//
				//	if(subtract1.doubleValue()> 0){
				//		chgFeesPage.setStoredPaymentMoney(balance);//用预存余额缴费的
				//	}else{
				//		//余额大于应付款
				//		chgFeesPage.setStoredPaymentMoney(chgFeesPage.getMoney());//用预存余额缴费的
				//	}
				//
				//	//本次结余
				//	currMoney = currMoney.subtract(chgFeesPage.getMoney());
				//	chgFeesPage.setPostBalance(currMoney);//本次结余
				//
				//	//balance = currMoney;
				//} else if ("02".equals(chargeFeeVo.getFeeWholeWay())) {
				//	chgFeesPage.setRecivedMoney(chgFeesPage.getMoney());//实收金额付款=该笔欠费金额
				//	chgFeesPage.setStoredPaymentMoney(new BigDecimal(0.0));//用预存余额缴费的
				//
				//	//本次结余
				//	currMoney = currMoney.subtract(chgFeesPage.getMoney());
				//	chgFeesPage.setPostBalance(currMoney);//本次结余
				//}

				chgFeesPage.setRemark("扣费");
				chgFeesPage.setStatus(1);
				chgFeesPage.setPaymentId(chgPayments.getId());
				chgFeesPage.setBatchNo(batchNo + "" + index);
				chgFeesPage.setChgSubFeesList(chgSubFeesLs);

				ChgFees chgFees = new ChgFees();
				BeanUtils.copyProperties(chgFeesPage, chgFees);
				feesService.saveMain(chgFees, chgFeesPage.getChgSubFeesList());

				/**3余额记录*/
				if (chgFeesPage.getMoney().doubleValue() > 0) {
					ChgStoreds storedFee = new ChgStoreds();
					storedFee.setAccCode(chgPayments.getAccCode());
					storedFee.setAccName(chgPayments.getAccName());
					storedFee.setAccountId(chgPayments.getAccountId());
					storedFee.setChargeId(chgFees.getId());
					storedFee.setPaymentId(chgPayments.getId());
					storedFee.setBatchNo(batchNo + "" + index);
					storedFee.setFeeStruckStatus("1");
					storedFee.setFeeTargetType("1");//缴费类型 1-收费,2-缴费,3-退费，4预存 5预存扣费
					storedFee.setFinancialDate(chgPayments.getFinancialDate());
					storedFee.setFinancialMonth(chgPayments.getFinancialMonth());
					storedFee.setStatus(1);

					storedFee.setPreBalance(chgFeesPage.getPreBalance());
					storedFee.setMoney(chgFeesPage.getMoney().setScale(2,BigDecimal.ROUND_HALF_UP));
					storedFee.setPostBalance(chgFeesPage.getPostBalance());

					storedFee.setChargeTime(DateUtils.getDate("yyyy-MM-dd HH:mm:ss"));
					storedFee.setCashierId(sysUser.getUsername());
					storedsService.save(storedFee);
				}
				/**4.对应的欠费记录删除，欠费历史增加*/

				HisArrearsPage hisArrearsPage = new HisArrearsPage();
				BeanUtils.copyProperties(chgArrear, hisArrearsPage);
				hisArrearsPage.setId(null);
				hisArrearsPage.setHisSubArrearList(chgHisSubFeesLs);

				HisArrears hisArrears = new HisArrears();
				BeanUtils.copyProperties(hisArrearsPage, hisArrears);
				hisArrears.setFeeId(chgFees.getId());
				hisArrearsService.saveMain(hisArrears, hisArrearsPage.getHisSubArrearList());

				List<ChgArrearExpenses> arrearExpensesList = chgArrearExpensesService.list(
						new LambdaQueryWrapper<ChgArrearExpenses>()
								.eq(ChgArrearExpenses::getArrearId, chgArrear.getId())
								.eq(ChgArrearExpenses::getDelFlag, 0));

				if (null != arrearExpensesList && arrearExpensesList.size() > 0) {
					for (ChgArrearExpenses arrearExpenses : arrearExpensesList) {
						HisArrearExpenses harrearExpenses = new HisArrearExpenses();
						BeanUtils.copyProperties(arrearExpenses, harrearExpenses);
						harrearExpenses.setId(null);
						hisArrearExpensesService.save(harrearExpenses);
					}
				}

				arrearsService.delAlienSubByMainId(chgArrear.getId());
				arrearsService.delMain(chgArrear.getId());
			}

			//预支付ID
			//paymentsService.update(new LambdaUpdateWrapper<ChgPayments>()
			//		.set(ChgPayments::getPrepayId,chgPayments.getPrepayId())
			//		.eq(ChgPayments::getId,chgPayments.getId()));
		}
		/**5.缴费账户余额变化*/

		//余额需要预存的
		if (chgPayments.getStoredPaymentMoney().doubleValue() > 0) {
			//还有剩余，是否预存  否则找零
			index++;
			//余额预存

			if(null != chgArrearLs && chgArrearLs.size()>0) {

				ChgStoreds chgStoreds = new ChgStoreds();
				chgStoreds.setAccCode(chgPayments.getAccCode());
				chgStoreds.setAccName(chgPayments.getAccName());
				//storeds.setChargeId(chgFees.getId());
				chgStoreds.setAccountId(arcAccount.getId());
				chgStoreds.setPaymentId(chgPayments.getId());
				chgStoreds.setBatchNo(batchNo + "" + index);
				chgStoreds.setFeeStruckStatus("1");
				chgStoreds.setFeeTargetType("4");///缴费类型 1-收费,2-缴费,3-退费，4预存 5预存扣费
				chgStoreds.setFinancialDate(DateUtils.formatDate());
				chgStoreds.setFinancialMonth(basePeriod.getMonth());
				chgStoreds.setStatus(1);

				chgStoreds.setPreBalance(arcAccount.getBalance());
				chgStoreds.setMoney(chgPayments.getStoredPaymentMoney());

				if ("01".equals(chargeFeeVo.getFeeWholeWay())) {
					//实收 上次余额一起参与进来收费了
					chgStoreds.setPostBalance(chgPayments.getStoredPaymentMoney());
				} else if ("02".equals(chargeFeeVo.getFeeWholeWay())) {
					//不扣余额时，=上次余额+本次剩余
					chgStoreds.setPostBalance(arcAccount.getBalance().add(chgPayments.getStoredPaymentMoney()));
				}

				chgStoreds.setChargeTime(DateUtils.getDate("yyyy-MM-dd HH:mm:ss"));
				chgStoreds.setCashierId(sysUser.getUsername());
				storedsService.save(chgStoreds);
			}
			//else{
			//	//没有勾选欠费过来，就是预存，前面已预存过了
			//}

		}

		//实付=付款-找零
		//BigDecimal real = chargeFeeVo.getPayFee().subtract(chargeFeeVo.getZeroFee());

		accountService.update(new LambdaUpdateWrapper<ArcAccount>()
				.set(ArcAccount::getBalance, totalMoney)
				.eq(ArcAccount::getId, arcAccount.getId()));

		rsObject.put("paymentId", chgPayments.getId());
		//rsObject.put("userFee", userFeeIdJson);
		rsObject.put("accountId", arcAccount.getId());
		rsObject.put("openId", arcAccount.getWeixinId());

		///**设置首页数据动态更新*/
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					/**设置首页数据动态更新-微信缴费成功*/
					indexData(null,null);
				} catch (Exception e) {
					e.printStackTrace();
				} finally {
					log.warn("首页数据动态更新");
				}
			}
		}).start();


		return Result.OK(rsObject);
		/***6票据*/

		//String billTypeId = chargeObj.getString("billTypeId");
		//String feePrintWay = chargeObj.getString("feePrintWay");
		//BvVersions currentVersion = bvVersionsService.getCurrentVersion(billTypeId);
		//
		//BvVouchers nextVouchers = bvVouchersService.getNextVouchers(
		//		chargeObj.getString("billTypeId"), currentVersion.getId());
		//
		//nextVouchers.setBillStatusId("02");
		//nextVouchers.setFinancialDate();
	}
	/**
	 * 缴费-后台核销
	 */
	@Override
	@Transactional
	public Result<?> mpHeXiaoCharge(ChgPayments chgPayments) {

		/**
		 * 缴费记录-从后台查询订单状态来核销
		 *
		 * feeChargeType 收费方式 收费类型1,全部收费,2余额预存（收费剩下）3部分收取（不支持）
		 * feePayType 支付方式 （现金、预存扣款、预存开票、POS、微信、支付宝。。。）
		 * feeWholeType 整收方式 1实收（先扣余额），2不扣余额实收
		 * feeTargetType 收费目的（收费、预存）
		 * feePayWay 支付方式
		 *
		 * recivedMoney
		 * payableMoney 应收金额
		 *
		 */

		LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();

		BasePeriod basePeriod = basePeriodService.getOne(
				new LambdaQueryWrapper<BasePeriod>().eq(BasePeriod::getIsUsed, 1));

		//缴费账户
		ArcAccount arcAccount = accountService.getById(chgPayments.getAccountId());
		if (null == arcAccount) {
			//缴费账户不存在
			return Result.error("缴费账户不存在");
		}

		boolean isPreStore=false;
		List<ChgArrears> chgArrearLs=null;
		BigDecimal arrearMoney =new BigDecimal(0.0);
		if( oConvertUtils.isEmpty(chgPayments.getArrearsIds()) || chgPayments.getArrearsIds().length()<5) {
			//没有欠费ID 预缴-充值
			isPreStore=true;
		}else if( oConvertUtils.isEmpty(chgPayments.getClientId()) || chgPayments.getClientId().length()<5) {
			//没有选择欠费核销，即为预缴,用 ClientId 暂存
			isPreStore=true;
		}else{
			//已选择核销的为准
			String arrearsIds =  chgPayments.getClientId();  // chgPayments.getArrearsIds();
			arrearsIds=arrearsIds.replace("[","");
			arrearsIds=arrearsIds.replace("]","");
			List<String> strings = Arrays.asList(arrearsIds.split(","));

			chgArrearLs= arrearsService.list(new LambdaQueryWrapper<ChgArrears>()
					.in(ChgArrears::getId, strings)
					.orderByAsc(ChgArrears::getReadMonth));

	//			chgArrearLs= arrearsService.listByIds(strings);
			if(null != chgArrearLs && chgArrearLs.size()>0){
				List<BigDecimal> arrearMoneyLs = chgArrearLs.stream().map(ChgArrears::getArrearMoney).collect(Collectors.toList());

				arrearMoney = chgArrearLs.stream().map(e -> e.getArrearMoney()).reduce(BigDecimal::add).get();//求和
				BigDecimal recivedMoney = chgArrearLs.stream().map(e -> e.getRecivedMoney()).reduce(BigDecimal::add).get();//求和
				arrearMoney=arrearMoney.subtract(recivedMoney).setScale(2,BigDecimal.ROUND_HALF_UP);
			}else{
				paymentsService.update(new LambdaUpdateWrapper<ChgPayments>()
						.set(ChgPayments::getDelFlag,1)//逻辑删除
						.eq(ChgPayments::getId,chgPayments.getId()));
				return Result.error("该缴费的欠费记录已不存在");
			}
		}

		//账户余额
		BigDecimal balance = arcAccount.getBalance();
		BigDecimal pre_balance = arcAccount.getBalance();
		//应收金额
		BigDecimal payableMoney = arrearMoney;//欠费账单
		//实缴
		BigDecimal realFee = chgPayments.getPayFee();
		//实收金额-付款
		BigDecimal recivedMoney = chgPayments.getPayFee()  ;
		if (null == recivedMoney) {
			recivedMoney = new BigDecimal(0.0);
		}


		//当前结余
		BigDecimal currMoney =new BigDecimal(0.0);
		//总余额=上次余额+实收-应收-找零
		BigDecimal totalMoney = balance.add(recivedMoney).subtract(payableMoney).setScale(2,BigDecimal.ROUND_HALF_UP);

		//整收方式 1实收（先扣余额），2不扣余额实收
//		if ("01".equals(chargeFeeVo.getFeeWholeWay())) {
			BigDecimal subtract = balance.add(recivedMoney).subtract(payableMoney).setScale(2,BigDecimal.ROUND_HALF_UP);
			if (subtract.doubleValue() < 0) {
				//支付金额不够
				return Result.error("支付金额不够");
			}
//			currMoney=balance.add(recivedMoney).subtract(chargeFeeVo.getZeroFee());
			currMoney=balance.add(recivedMoney);
//		}

		//返回
		JSONObject rsObject = new JSONObject();
		//用户收费对应ID
		//JSONObject userFeeIdJson = new JSONObject();

		Set<String> cusSet = new HashSet<>();
		//批次号
		Integer index = 0;
		String batchNo = chgPayments.getBatchNo();

		index++;
		//余额预存
		ChgStoreds storeds = new ChgStoreds();
		storeds.setAccCode(chgPayments.getAccCode());
		storeds.setAccName(chgPayments.getAccName());
		//storeds.setChargeId(chgFees.getId());
		storeds.setAccountId(arcAccount.getId());
		storeds.setPaymentId(chgPayments.getId());
		storeds.setBatchNo(batchNo + "" + index);
		storeds.setFeeStruckStatus("1");
		//没有勾选欠费过来，就默认充值预存
		storeds.setFeeTargetType("4");///缴费类型 1-收费,2-缴费,3-退费，4预存 5预存扣费

		storeds.setFinancialDate(chgPayments.getFinancialDate());
		storeds.setFinancialMonth(chgPayments.getFinancialMonth());
		storeds.setStatus(1);
		storeds.setPreBalance(arcAccount.getBalance());
//		storeds.setMoney(recivedMoney.subtract(chargeFeeVo.getZeroFee()));//付款-找零
		storeds.setMoney(recivedMoney);//付款-找零
		storeds.setPostBalance(storeds.getPreBalance().add(storeds.getMoney()));//余额+本次缴费

		storeds.setChargeTime(DateUtils.getDate("yyyy-MM-dd HH:mm:ss"));
		storeds.setCashierId(sysUser.getUsername());
		storedsService.save(storeds);

		//核销状态修改-ClientId() -> ArrearsIds
		paymentsService.update(new LambdaUpdateWrapper<ChgPayments>()
				.set(ChgPayments::getStatus,1)
				.set(ChgPayments::getSyncFlag,1)//同步核销状态
				.set(ChgPayments::getPostMoney,totalMoney)//预缴本次余额修改
				.set(ChgPayments::getRemark,isPreStore ? "预缴-手动核销":"缴费-手动核销")//预缴本次余额修改
				.set(ChgPayments::getTransactionId,chgPayments.getTransactionId())
				.set(ChgPayments::getArrearsIds,chgPayments.getClientId())
				.eq(ChgPayments::getId,chgPayments.getId()));


//		if(null !=chgArrearLs && chgArrearLs.size()>0 ){


		//校验余额，
//		List<ChgArrears> chgArrearLs= arrearsService.listByIds(arrearIds);
		index++;
		if(null != chgArrearLs && chgArrearLs.size()>0){
			for (ChgArrears chgArrear : chgArrearLs) {
				/**2 收费、收费明细 */
				ChgFeesPage chgFeesPage = new ChgFeesPage();
				ArrayList<ChgSubFees> chgSubFeesLs = new ArrayList<>();
				/**历史欠费明细*/
				ArrayList<HisSubArrear> chgHisSubFeesLs = new ArrayList<>();

				//欠费明细
				List<ChgSubArrear> subArrearList = subArrearService.selectByMainId(chgArrear.getId());
				for (ChgSubArrear subArrear : subArrearList) {
					ChgSubFees subFees = new ChgSubFees();
					subFees.setNatureId(subArrear.getNatureId());
					subFees.setPriceId(subArrear.getPriceId());
					subFees.setPrice(subArrear.getPrice());
					subFees.setItemCode(subArrear.getItemCode());
					subFees.setSubExpenseId(subArrear.getSubExpenseId());
					subFees.setAmount(subArrear.getAmount());
					subFees.setTierNo(subArrear.getTierNo());
					subFees.setVatMoney(subArrear.getVatMoney());
					subFees.setMoney(subArrear.getArrearMoney());
					subFees.setDerateMoney(subArrear.getDerateMoney());// 减免费用
					chgSubFeesLs.add(subFees);

					HisSubArrear hisSubArrear = new HisSubArrear();
					BeanUtils.copyProperties(subArrear, hisSubArrear);
					hisSubArrear.setId(null);
					chgHisSubFeesLs.add(hisSubArrear);
				}

				chgFeesPage.setBookId(chgArrear.getBookId());
				chgFeesPage.setBeginScale(chgArrear.getBeginScale());
				chgFeesPage.setEndScale(chgArrear.getEndScale());
				chgFeesPage.setReadMonth(chgArrear.getReadMonth());
				chgFeesPage.setReaderId(chgArrear.getReaderId());
				chgFeesPage.setAmount(chgArrear.getArrearAmount());
				chgFeesPage.setCusId(chgArrear.getCusId());
				chgFeesPage.setCusName(chgArrear.getCusName());
				chgFeesPage.setFeeChargeType("3");
				chgFeesPage.setFeeStruckStatus(1);
				chgFeesPage.setFeePayWay(chgPayments.getFeePayWay());//支付方式
				chgFeesPage.setFinancialDate(chgPayments.getFinancialDate());
				chgFeesPage.setFinancialMonth(chgPayments.getFinancialMonth());

				chgFeesPage.setTotalMoney(chgArrear.getTotalMoney());//水费
				chgFeesPage.setPenalty(chgArrear.getPenalty());//违约金
				chgFeesPage.setWuMoney(chgArrear.getWuMoney());//污水
				chgFeesPage.setAlienMoney(chgArrear.getAlienMoney());//杂项费用
				chgFeesPage.setJiMoney(chgArrear.getJiMoney());//季加
				chgFeesPage.setJyMoney(chgArrear.getJyMoney());//二加压
				chgFeesPage.setLjMoney(chgArrear.getLjMoney());//垃圾费
				chgFeesPage.setDerateMoney(chgArrear.getDerateMoney());// 减免费用

				chgFeesPage.setPreBalance(pre_balance);//上次余额=本次缴费前的
				//实欠=欠费-已收
				BigDecimal realArrearMoney = chgArrear.getArrearMoney().subtract(chgArrear.getRecivedMoney());
				chgFeesPage.setMoney(realArrearMoney);//该笔欠费金额

				/** 先缴费充值，后收费，都是从预存余额扣除*/
				chgFeesPage.setRecivedMoney(new BigDecimal(0.0));//实收=0
				chgFeesPage.setStoredPaymentMoney(chgFeesPage.getMoney().setScale(2,BigDecimal.ROUND_HALF_UP));//用预存余额缴费的,

				//本次结余
				currMoney = currMoney.subtract(chgFeesPage.getMoney()).setScale(2,BigDecimal.ROUND_HALF_UP);
				chgFeesPage.setPostBalance(currMoney);
				pre_balance=currMoney;

				////整收方式 1实收（先扣余额），2不扣余额实收
				//if ("01".equals(chargeFeeVo.getFeeWholeWay())) {
				//	chgFeesPage.setRecivedMoney(chgFeesPage.getMoney());//实收=该笔欠费金额
				//
				//	BigDecimal subtract1 = chgFeesPage.getMoney().subtract(currMoney);
				//
				//	if(subtract1.doubleValue()> 0){
				//		chgFeesPage.setStoredPaymentMoney(balance);//用预存余额缴费的
				//	}else{
				//		//余额大于应付款
				//		chgFeesPage.setStoredPaymentMoney(chgFeesPage.getMoney());//用预存余额缴费的
				//	}
				//
				//	//本次结余
				//	currMoney = currMoney.subtract(chgFeesPage.getMoney());
				//	chgFeesPage.setPostBalance(currMoney);//本次结余
				//
				//	//balance = currMoney;
				//} else if ("02".equals(chargeFeeVo.getFeeWholeWay())) {
				//	chgFeesPage.setRecivedMoney(chgFeesPage.getMoney());//实收金额付款=该笔欠费金额
				//	chgFeesPage.setStoredPaymentMoney(new BigDecimal(0.0));//用预存余额缴费的
				//
				//	//本次结余
				//	currMoney = currMoney.subtract(chgFeesPage.getMoney());
				//	chgFeesPage.setPostBalance(currMoney);//本次结余
				//}

				chgFeesPage.setRemark("扣费");
				chgFeesPage.setStatus(1);
				chgFeesPage.setPaymentId(chgPayments.getId());
				chgFeesPage.setBatchNo(batchNo + "" + index);
				chgFeesPage.setChgSubFeesList(chgSubFeesLs);

				ChgFees chgFees = new ChgFees();
				BeanUtils.copyProperties(chgFeesPage, chgFees);
				feesService.saveMain(chgFees, chgFeesPage.getChgSubFeesList());

				/**3余额记录*/
				if (chgFeesPage.getMoney().doubleValue() > 0) {
					ChgStoreds storedFee = new ChgStoreds();
					storedFee.setAccCode(chgPayments.getAccCode());
					storedFee.setAccName(chgPayments.getAccName());
					storedFee.setAccountId(chgPayments.getAccountId());
					storedFee.setChargeId(chgFees.getId());
					storedFee.setPaymentId(chgPayments.getId());
					storedFee.setBatchNo(batchNo + "" + index);
					storedFee.setFeeStruckStatus("1");
					storedFee.setFeeTargetType("1");//缴费类型 1-收费,2-缴费,3-退费，4预存 5预存扣费
					storedFee.setFinancialDate(chgPayments.getFinancialDate());
					storedFee.setFinancialMonth(chgPayments.getFinancialMonth());
					storedFee.setStatus(1);

					storedFee.setPreBalance(chgFeesPage.getPreBalance());
					storedFee.setMoney(chgFeesPage.getMoney().setScale(2,BigDecimal.ROUND_HALF_UP));
					storedFee.setPostBalance(chgFeesPage.getPostBalance());

					storedFee.setChargeTime(DateUtils.getDate("yyyy-MM-dd HH:mm:ss"));
					storedFee.setCashierId(sysUser.getUsername());
					storedsService.save(storedFee);
				}
				/**4.对应的欠费记录删除，欠费历史增加*/

				HisArrearsPage hisArrearsPage = new HisArrearsPage();
				BeanUtils.copyProperties(chgArrear, hisArrearsPage);
				hisArrearsPage.setId(null);
				hisArrearsPage.setHisSubArrearList(chgHisSubFeesLs);

				HisArrears hisArrears = new HisArrears();
				BeanUtils.copyProperties(hisArrearsPage, hisArrears);
				hisArrears.setFeeId(chgFees.getId());
				hisArrearsService.saveMain(hisArrears, hisArrearsPage.getHisSubArrearList());

				List<ChgArrearExpenses> arrearExpensesList = chgArrearExpensesService.list(
						new LambdaQueryWrapper<ChgArrearExpenses>()
								.eq(ChgArrearExpenses::getArrearId, chgArrear.getId())
								.eq(ChgArrearExpenses::getDelFlag, 0));

				if (null != arrearExpensesList && arrearExpensesList.size() > 0) {
					for (ChgArrearExpenses arrearExpenses : arrearExpensesList) {
						HisArrearExpenses harrearExpenses = new HisArrearExpenses();
						BeanUtils.copyProperties(arrearExpenses, harrearExpenses);
						harrearExpenses.setId(null);
						hisArrearExpensesService.save(harrearExpenses);
					}
				}

				arrearsService.delAlienSubByMainId(chgArrear.getId());
				arrearsService.delMain(chgArrear.getId());
			}
			/**设置首页数据动态更新-统一走子线程*/
			//this.indexData(null,null);

			//预支付ID
			//paymentsService.update(new LambdaUpdateWrapper<ChgPayments>()
			//		.set(ChgPayments::getPrepayId,chgPayments.getPrepayId())
			//		.eq(ChgPayments::getId,chgPayments.getId()));
		}
		/**5.缴费账户余额变化*/

		//余额需要预存的
		if (chgPayments.getStoredPaymentMoney().doubleValue() > 0) {
			//还有剩余，是否预存  否则找零
			index++;
			//余额预存

			if(null != chgArrearLs && chgArrearLs.size()>0) {

				ChgStoreds chgStoreds = new ChgStoreds();
				chgStoreds.setAccCode(chgPayments.getAccCode());
				chgStoreds.setAccName(chgPayments.getAccName());
				//storeds.setChargeId(chgFees.getId());
				chgStoreds.setAccountId(arcAccount.getId());
				chgStoreds.setPaymentId(chgPayments.getId());
				chgStoreds.setBatchNo(batchNo + "" + index);
				chgStoreds.setFeeStruckStatus("1");
				chgStoreds.setFeeTargetType("4");///缴费类型 1-收费,2-缴费,3-退费，4预存 5预存扣费
				chgStoreds.setFinancialDate(DateUtils.formatDate());
				chgStoreds.setFinancialMonth(basePeriod.getMonth());
				chgStoreds.setStatus(1);

				chgStoreds.setPreBalance(arcAccount.getBalance());
				chgStoreds.setMoney(chgPayments.getStoredPaymentMoney());

				//if ("01".equals(chargeFeeVo.getFeeWholeWay())) {
					//实收 上次余额一起参与进来收费了
					chgStoreds.setPostBalance(chgPayments.getStoredPaymentMoney());
				//} else if ("02".equals(chargeFeeVo.getFeeWholeWay())) {
				//	//不扣余额时，=上次余额+本次剩余
				//	chgStoreds.setPostBalance(arcAccount.getBalance().add(chgPayments.getStoredPaymentMoney()));
				//}

				chgStoreds.setChargeTime(DateUtils.getDate("yyyy-MM-dd HH:mm:ss"));
				chgStoreds.setCashierId(sysUser.getUsername());
				storedsService.save(chgStoreds);

				/**设置首页数据动态更新 - 预存-统一走子线程*/
				//this.indexData(null,null);
			}
			//else{
			//	//没有勾选欠费过来，就是预存，前面已预存过了
			//}

		}

		//实付=付款-找零
		//BigDecimal real = chargeFeeVo.getPayFee().subtract(chargeFeeVo.getZeroFee());

		accountService.update(new LambdaUpdateWrapper<ArcAccount>()
				.set(ArcAccount::getBalance, totalMoney)
				.eq(ArcAccount::getId, arcAccount.getId()));

		rsObject.put("paymentId", chgPayments.getId());
		//rsObject.put("userFee", userFeeIdJson);
		rsObject.put("accountId", arcAccount.getId());
		rsObject.put("openId", arcAccount.getWeixinId());

		///**设置首页数据动态更新*/
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					/**设置首页数据动态更新-后台核销*/
					indexData(null,null);
				} catch (Exception e) {
					e.printStackTrace();
				} finally {
					log.warn("首页数据动态更新");
				}
			}
		}).start();

		return Result.OK(rsObject);
		/***6票据*/

		//String billTypeId = chargeObj.getString("billTypeId");
		//String feePrintWay = chargeObj.getString("feePrintWay");
		//BvVersions currentVersion = bvVersionsService.getCurrentVersion(billTypeId);
		//
		//BvVouchers nextVouchers = bvVouchersService.getNextVouchers(
		//		chargeObj.getString("billTypeId"), currentVersion.getId());
		//
		//nextVouchers.setBillStatusId("02");
		//nextVouchers.setFinancialDate();
	}
	/**
	 * 缴费-后台核销
	 */
	@Override
	@Transactional
	public JSONObject abcHeXiaoCharge(JSONObject cacheMemObj ) {

		/**
		 * 缴费记录-农行支付成功后核销
		 *
		 * feeChargeType 收费方式 收费类型1,全部收费,2余额预存（收费剩下）3部分收取（不支持）
		 * feePayType 支付方式 （现金、预存扣款、预存开票、POS、微信、支付宝。。。）
		 * feeWholeType 整收方式 1实收（先扣余额），2不扣余额实收
		 * feeTargetType 收费目的（收费、预存）
		 * feePayWay 支付方式
		 *
		 * recivedMoney
		 * payableMoney 应收金额
		 *
		 */
		JSONObject resObj = new JSONObject();
		//设置租户
		TenantContext.setTenant(cacheMemObj.getString("tenantId"));
		System.out.println(cacheMemObj.toJSONString());
		ChgPayments chgPayments= paymentsService.getById(cacheMemObj.getString("paymentId"));
		chgPayments.setArrearsIds(cacheMemObj.getString("arrearIds"));
		chgPayments.setClientId(cacheMemObj.getString("arrearIds") );
		chgPayments.setSerialNo(cacheMemObj.getString("transSeqNum"));//缴费中心交易序列号
		chgPayments.setTransactionId(cacheMemObj.getString("traceNo"));//缴费中心流水号
		//BigDecimal receFee = cacheMemObj.getBigDecimal("receFee");// 应缴金额（欠费金额）
		String payBillAmt = cacheMemObj.getString("payBillAmt");
		BigDecimal payMoney =null;
		try{
			payMoney = new BigDecimal(payBillAmt).setScale(2,BigDecimal.ROUND_HALF_UP);
		}catch (Exception e){
			e.printStackTrace();
			resObj.put("code","JH02");
			resObj.put("msg","支付金额格式不对");
			return resObj;
		}
		if( 1== chgPayments.getSyncFlag()){
			resObj.put("code","JH02");
			resObj.put("msg","该缴费已核销");
			return resObj;
		}
		if( !"5".equals(chgPayments.getFeePayWay())){
			resObj.put("code","JH02");
			resObj.put("msg","该缴费方式不是农行商E付");
			return resObj;
		}

		String sysUser = cacheMemObj.getString("cashier");

		BasePeriod basePeriod = basePeriodService.getOne(
				new LambdaQueryWrapper<BasePeriod>().eq(BasePeriod::getIsUsed, 1));

		//缴费账户
		ArcAccount arcAccount = accountService.getById(chgPayments.getAccountId());
		if (null == arcAccount) {
			//缴费账户不存在
			resObj.put("code","JH02");
			resObj.put("msg","缴费账户不存在");
			return resObj;
		}

		boolean isPreStore=false;
		List<ChgArrears> chgArrearLs=null;
		BigDecimal arrearMoney =new BigDecimal(0.0);
		if( oConvertUtils.isEmpty(chgPayments.getArrearsIds()) || chgPayments.getArrearsIds().length()<5) {
			//没有欠费ID 预缴-充值
			isPreStore=true;
		}else if( oConvertUtils.isEmpty(chgPayments.getClientId()) || chgPayments.getClientId().length()<5) {
			//没有选择欠费核销，即为预缴,用 ClientId 暂存
			isPreStore=true;
		}else{
			//已选择核销的为准
			String arrearsIds =  chgPayments.getClientId();  // chgPayments.getArrearsIds();
			arrearsIds=arrearsIds.replace("[","");
			arrearsIds=arrearsIds.replace("]","");
			List<String> strings = Arrays.asList(arrearsIds.split(","));

			chgArrearLs= arrearsService.list(new LambdaQueryWrapper<ChgArrears>()
					.in(ChgArrears::getId, strings)
					.orderByAsc(ChgArrears::getReadMonth));
			if(null != chgArrearLs && chgArrearLs.size()>0){
				List<BigDecimal> arrearMoneyLs = chgArrearLs.stream().map(ChgArrears::getArrearMoney).collect(Collectors.toList());

				arrearMoney = chgArrearLs.stream().map(e -> e.getArrearMoney()).reduce(BigDecimal::add).get();//求和
				BigDecimal recivedMoney = chgArrearLs.stream().map(e -> e.getRecivedMoney()).reduce(BigDecimal::add).get();//求和
				arrearMoney=arrearMoney.subtract(recivedMoney).setScale(2,BigDecimal.ROUND_HALF_UP);
			}else{
				paymentsService.update(new LambdaUpdateWrapper<ChgPayments>()
						.set(ChgPayments::getDelFlag,1)//逻辑删除
						.eq(ChgPayments::getId,chgPayments.getId()));

				resObj.put("code","JH02");
				resObj.put("msg","该缴费的欠费记录已不存在");
				return resObj;
			}
		}

		//账户余额
		BigDecimal balance = arcAccount.getBalance();
		BigDecimal pre_balance = arcAccount.getBalance();
		//应收金额
		BigDecimal payableMoney = arrearMoney;//欠费账单
		//实缴
		//BigDecimal realFee = payMoney;// chgPayments.getPayFee();
		//实收金额
		BigDecimal recivedMoney = payMoney;// chgPayments.getPayFee()  ;
		if (null == recivedMoney) {
			recivedMoney = new BigDecimal(0.0);
		}

		//当前结余
		BigDecimal currMoney =new BigDecimal(0.0);
		//总余额=上次余额+实收-应收-找零
		BigDecimal totalMoney = balance.add(recivedMoney).subtract(payableMoney).setScale(2,BigDecimal.ROUND_HALF_UP);

		//整收方式 1实收（先扣余额），2不扣余额实收
//		if ("01".equals(chargeFeeVo.getFeeWholeWay())) {
			BigDecimal subtract = balance.add(recivedMoney).subtract(payableMoney).setScale(2,BigDecimal.ROUND_HALF_UP);
			if (subtract.doubleValue() < 0) {
				//支付金额不够
				resObj.put("code","JH05");
				resObj.put("msg","支付金额不足");
				return resObj;
			}
//			currMoney=balance.add(recivedMoney).subtract(chargeFeeVo.getZeroFee());
			currMoney=balance.add(recivedMoney);
//		}

		//返回
		JSONObject rsObject = new JSONObject();
		//用户收费对应ID
		//JSONObject userFeeIdJson = new JSONObject();

		Set<String> cusSet = new HashSet<>();
		//批次号
		Integer index = 0;
		String batchNo = chgPayments.getBatchNo();

		index++;
		//余额预存
		ChgStoreds storeds = new ChgStoreds();
		storeds.setAccCode(chgPayments.getAccCode());
		storeds.setAccName(chgPayments.getAccName());
		//storeds.setChargeId(chgFees.getId());
		storeds.setAccountId(arcAccount.getId());
		storeds.setPaymentId(chgPayments.getId());
		storeds.setBatchNo(batchNo + "" + index);
		storeds.setFeeStruckStatus("1");
		//没有勾选欠费过来，就默认充值预存
		storeds.setFeeTargetType("4");///缴费类型 1-收费,2-缴费,3-退费，4预存 5预存扣费

		storeds.setFinancialDate(chgPayments.getFinancialDate());
		storeds.setFinancialMonth(chgPayments.getFinancialMonth());
		storeds.setStatus(1);
		storeds.setPreBalance(arcAccount.getBalance());
//		storeds.setMoney(recivedMoney.subtract(chargeFeeVo.getZeroFee()));//付款-找零
		storeds.setMoney(recivedMoney);//付款-找零
		storeds.setPostBalance(storeds.getPreBalance().add(storeds.getMoney()));//余额+本次缴费

		storeds.setChargeTime(DateUtils.getDate("yyyy-MM-dd HH:mm:ss"));
		storeds.setCashierId(sysUser);
		storedsService.save(storeds);

		//核销状态修改-ClientId() -> ArrearsIds
		paymentsService.update(new LambdaUpdateWrapper<ChgPayments>()
				.set(ChgPayments::getStatus,1)
				.set(ChgPayments::getSyncFlag,1)//同步核销状态
				.set(ChgPayments::getPayFee,recivedMoney)//实付金额
				.set(ChgPayments::getPostMoney,totalMoney)//预缴本次余额修改
				.set(ChgPayments::getRemark,isPreStore ? "预缴-农行核销":"缴费-农行核销")//预缴本次余额修改
				.set(ChgPayments::getUpdateTime,new Date())//更新时间
				.set(ChgPayments::getUpdateBy,sysUser)
				.set(ChgPayments::getSerialNo,chgPayments.getSerialNo())
				.set(ChgPayments::getTransactionId,chgPayments.getTransactionId())
				.set(ChgPayments::getArrearsIds,chgPayments.getClientId())
				.eq(ChgPayments::getId,chgPayments.getId()));
		//校验余额，
		index++;
		if(null != chgArrearLs && chgArrearLs.size()>0){
			for (ChgArrears chgArrear : chgArrearLs) {
				/**2 收费、收费明细 */
				ChgFeesPage chgFeesPage = new ChgFeesPage();
				ArrayList<ChgSubFees> chgSubFeesLs = new ArrayList<>();
				/**历史欠费明细*/
				ArrayList<HisSubArrear> chgHisSubFeesLs = new ArrayList<>();

				//欠费明细
				List<ChgSubArrear> subArrearList = subArrearService.selectByMainId(chgArrear.getId());
				for (ChgSubArrear subArrear : subArrearList) {
					ChgSubFees subFees = new ChgSubFees();
					subFees.setNatureId(subArrear.getNatureId());
					subFees.setPriceId(subArrear.getPriceId());
					subFees.setPrice(subArrear.getPrice());
					subFees.setItemCode(subArrear.getItemCode());
					subFees.setSubExpenseId(subArrear.getSubExpenseId());
					subFees.setAmount(subArrear.getAmount());
					subFees.setTierNo(subArrear.getTierNo());
					subFees.setVatMoney(subArrear.getVatMoney());
					subFees.setMoney(subArrear.getArrearMoney());
					subFees.setDerateMoney(subArrear.getDerateMoney());
					chgSubFeesLs.add(subFees);

					HisSubArrear hisSubArrear = new HisSubArrear();
					BeanUtils.copyProperties(subArrear, hisSubArrear);
					hisSubArrear.setId(null);
					chgHisSubFeesLs.add(hisSubArrear);
				}

				chgFeesPage.setBookId(chgArrear.getBookId());
				chgFeesPage.setBeginScale(chgArrear.getBeginScale());
				chgFeesPage.setEndScale(chgArrear.getEndScale());
				chgFeesPage.setReadMonth(chgArrear.getReadMonth());
				chgFeesPage.setReaderId(chgArrear.getReaderId());
				chgFeesPage.setAmount(chgArrear.getArrearAmount());
				chgFeesPage.setCusId(chgArrear.getCusId());
				chgFeesPage.setCusName(chgArrear.getCusName());
				chgFeesPage.setFeeChargeType("3");
				chgFeesPage.setFeeStruckStatus(1);
				chgFeesPage.setFeePayWay(chgPayments.getFeePayWay());//支付方式
				chgFeesPage.setFinancialDate(chgPayments.getFinancialDate());
				chgFeesPage.setFinancialMonth(chgPayments.getFinancialMonth());

				chgFeesPage.setTotalMoney(chgArrear.getTotalMoney());//水费
				chgFeesPage.setPenalty(chgArrear.getPenalty());//违约金
				chgFeesPage.setWuMoney(chgArrear.getWuMoney());//污水
				chgFeesPage.setAlienMoney(chgArrear.getAlienMoney());//杂项费用
				chgFeesPage.setJiMoney(chgArrear.getJiMoney());//季加
				chgFeesPage.setJyMoney(chgArrear.getJyMoney());//二加压
				chgFeesPage.setLjMoney(chgArrear.getLjMoney());//垃圾费
				chgFeesPage.setDerateMoney(chgArrear.getDerateMoney());// 减免费用

				chgFeesPage.setPreBalance(pre_balance);//上次余额=本次缴费前的
				//实欠=欠费-已收
				BigDecimal realArrearMoney = chgArrear.getArrearMoney().subtract(chgArrear.getRecivedMoney());
				chgFeesPage.setMoney(realArrearMoney);//该笔欠费金额

				/** 先缴费充值，后收费，都是从预存余额扣除*/
				chgFeesPage.setRecivedMoney(new BigDecimal(0.0));//实收=0
				chgFeesPage.setStoredPaymentMoney(chgFeesPage.getMoney().setScale(2,BigDecimal.ROUND_HALF_UP));//用预存余额缴费的,

				//本次结余
				currMoney = currMoney.subtract(chgFeesPage.getMoney()).setScale(2,BigDecimal.ROUND_HALF_UP);
				chgFeesPage.setPostBalance(currMoney);
				pre_balance=currMoney;

				chgFeesPage.setRemark("扣费");
				chgFeesPage.setStatus(1);
				chgFeesPage.setPaymentId(chgPayments.getId());
				chgFeesPage.setBatchNo(batchNo + "" + index);
				chgFeesPage.setChgSubFeesList(chgSubFeesLs);

				ChgFees chgFees = new ChgFees();
				BeanUtils.copyProperties(chgFeesPage, chgFees);
				feesService.saveMain(chgFees, chgFeesPage.getChgSubFeesList());

				/**3余额记录*/
				if (chgFeesPage.getMoney().doubleValue() > 0) {
					ChgStoreds storedFee = new ChgStoreds();
					storedFee.setAccCode(chgPayments.getAccCode());
					storedFee.setAccName(chgPayments.getAccName());
					storedFee.setAccountId(chgPayments.getAccountId());
					storedFee.setChargeId(chgFees.getId());
					storedFee.setPaymentId(chgPayments.getId());
					storedFee.setBatchNo(batchNo + "" + index);
					storedFee.setFeeStruckStatus("1");
					storedFee.setFeeTargetType("1");//缴费类型 1-收费,2-缴费,3-退费，4预存 5预存扣费
					storedFee.setFinancialDate(chgPayments.getFinancialDate());
					storedFee.setFinancialMonth(chgPayments.getFinancialMonth());
					storedFee.setStatus(1);

					storedFee.setPreBalance(chgFeesPage.getPreBalance());
					storedFee.setMoney(chgFeesPage.getMoney().setScale(2,BigDecimal.ROUND_HALF_UP));
					storedFee.setPostBalance(chgFeesPage.getPostBalance());

					storedFee.setChargeTime(DateUtils.getDate("yyyy-MM-dd HH:mm:ss"));
					storedFee.setCashierId(sysUser);
					storedsService.save(storedFee);
				}
				/**4.对应的欠费记录删除，欠费历史增加*/

				HisArrearsPage hisArrearsPage = new HisArrearsPage();
				BeanUtils.copyProperties(chgArrear, hisArrearsPage);
				hisArrearsPage.setId(null);
				hisArrearsPage.setHisSubArrearList(chgHisSubFeesLs);

				HisArrears hisArrears = new HisArrears();
				BeanUtils.copyProperties(hisArrearsPage, hisArrears);
				hisArrears.setFeeId(chgFees.getId());
				hisArrearsService.saveMain(hisArrears, hisArrearsPage.getHisSubArrearList());

				List<ChgArrearExpenses> arrearExpensesList = chgArrearExpensesService.list(
						new LambdaQueryWrapper<ChgArrearExpenses>()
								.eq(ChgArrearExpenses::getArrearId, chgArrear.getId())
								.eq(ChgArrearExpenses::getDelFlag, 0));

				if (null != arrearExpensesList && arrearExpensesList.size() > 0) {
					for (ChgArrearExpenses arrearExpenses : arrearExpensesList) {
						HisArrearExpenses harrearExpenses = new HisArrearExpenses();
						BeanUtils.copyProperties(arrearExpenses, harrearExpenses);
						harrearExpenses.setId(null);
						hisArrearExpensesService.save(harrearExpenses);
					}
				}

				arrearsService.delAlienSubByMainId(chgArrear.getId());
				arrearsService.delMain(chgArrear.getId());
			}
		}
		/**5.缴费账户余额变化*/

		//余额需要预存的
		if (totalMoney.doubleValue() > 0) {
			//还有剩余，是否预存  否则找零
			index++;
			//余额预存明细

			//if(null != chgArrearLs && chgArrearLs.size()>0) {

				ChgStoreds chgStoreds = new ChgStoreds();
				chgStoreds.setAccCode(chgPayments.getAccCode());
				chgStoreds.setAccName(chgPayments.getAccName());
				//storeds.setChargeId(chgFees.getId());
				chgStoreds.setAccountId(arcAccount.getId());
				chgStoreds.setPaymentId(chgPayments.getId());
				chgStoreds.setBatchNo(batchNo + "" + index);
				chgStoreds.setFeeStruckStatus("1");
				chgStoreds.setFeeTargetType("4");///缴费类型 1-收费,2-缴费,3-退费，4预存 5预存扣费
				chgStoreds.setFinancialDate(DateUtils.formatDate());
				chgStoreds.setFinancialMonth(basePeriod.getMonth());
				chgStoreds.setStatus(1);

				chgStoreds.setPreBalance(arcAccount.getBalance());

				chgStoreds.setMoney(totalMoney);

				//if ("01".equals(chargeFeeVo.getFeeWholeWay())) {
					//实收 上次余额一起参与进来收费了
					chgStoreds.setPostBalance(totalMoney);
				//} else if ("02".equals(chargeFeeVo.getFeeWholeWay())) {
				//	//不扣余额时，=上次余额+本次剩余
				//	chgStoreds.setPostBalance(arcAccount.getBalance().add(chgPayments.getStoredPaymentMoney()));
				//}

				chgStoreds.setChargeTime(DateUtils.getDate("yyyy-MM-dd HH:mm:ss"));
				chgStoreds.setCashierId(sysUser);
				storedsService.save(chgStoreds);

				/**设置首页数据动态更新 - 预存-统一走子线程*/
				//this.indexData(null,null);
			//}
		}
		//实付=付款-找零
		//BigDecimal real = chargeFeeVo.getPayFee().subtract(chargeFeeVo.getZeroFee());

		accountService.update(new LambdaUpdateWrapper<ArcAccount>()
				.set(ArcAccount::getBalance, totalMoney)
				.eq(ArcAccount::getId, arcAccount.getId()));

		rsObject.put("paymentId", chgPayments.getId());
		//rsObject.put("userFee", userFeeIdJson);
		rsObject.put("accountId", arcAccount.getId());
		rsObject.put("openId", arcAccount.getWeixinId());

		rsObject.put("code","0000");
		rsObject.put("msg","缴费成功");
		return rsObject;

		/***6票据*/

		//String billTypeId = chargeObj.getString("billTypeId");
		//String feePrintWay = chargeObj.getString("feePrintWay");
		//BvVersions currentVersion = bvVersionsService.getCurrentVersion(billTypeId);
		//
		//BvVouchers nextVouchers = bvVouchersService.getNextVouchers(
		//		chargeObj.getString("billTypeId"), currentVersion.getId());
		//
		//nextVouchers.setBillStatusId("02");
		//nextVouchers.setFinancialDate();
	}
	/**
	 * 预存自动收费
	 */
	@Override
	@Transactional
	public Result<?> storedCharge(ChgArrears arrear) {

		/**
		 * 缴费记录只跟收支有关
		 *
		 * 打印方式
		 * 票据类型
		 *
		 */
		//LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();

		//查验是否跳月缴费的
		int count = arrearsService.count(new LambdaQueryWrapper<ChgArrears>()
				.eq(ChgArrears::getDelFlag, 0)
				.eq(ChgArrears::getCusId,arrear.getCusId())
				.lt(ChgArrears::getReadMonth, arrear.getReadMonth())
				.notIn(ChgArrears::getId, arrear.getId())
				.orderByAsc(ChgArrears::getReadMonth));
		if (count > 0) {
			//存在跳月收费
			log.warn(arrear.getCusId()+"不允许跨月收费");
			return Result.error("不允许跨月收费");
		}

		BasePeriod basePeriod = basePeriodService.getOne(
				new LambdaQueryWrapper<BasePeriod>().eq(BasePeriod::getIsUsed, 1));

		//缴费账户
		ArcAccount arcAccount = accountService.getById(arrear.getAccId());
		if (null == arcAccount) {
			//缴费账户不存在
			log.warn(arrear.getCusId()+"缴费账户不存在");
			return Result.error("缴费账户不存在");
		}
		//账户余额
		BigDecimal balance = arcAccount.getBalance();
		BigDecimal pre_balance = arcAccount.getBalance();
		BigDecimal balance2 = arcAccount.getBalance();

		//返回
		JSONObject rsObject = new JSONObject();
		//批次号
		Integer index = 0;
		String batchNo = createBatchNo();

		index++;

		/**2 收费、收费明细 */
		ChgFeesPage chgFeesPage = new ChgFeesPage();
		ArrayList<ChgSubFees> chgSubFeesLs = new ArrayList<>();
		/**历史欠费明细*/
		ArrayList<HisSubArrear> chgHisSubFeesLs = new ArrayList<>();

		if(balance.doubleValue()>0) {
			chgFeesPage.setBookId(arrear.getBookId());
			chgFeesPage.setBeginScale(arrear.getBeginScale());
			chgFeesPage.setEndScale(arrear.getEndScale());
			chgFeesPage.setReadMonth(arrear.getReadMonth());
			chgFeesPage.setReaderId(arrear.getReaderId());
			chgFeesPage.setAmount(arrear.getArrearAmount());
			chgFeesPage.setCusId(arrear.getCusId());
			chgFeesPage.setCusName(arrear.getCusName());
			chgFeesPage.setFeeStruckStatus(1);
			chgFeesPage.setFeePayWay("4");//支付方式:余额
			chgFeesPage.setFinancialDate(DateUtils.getDate("yyyy-MM-dd HH:mm:ss"));
			chgFeesPage.setFinancialMonth(basePeriod.getMonth());

			chgFeesPage.setTotalMoney(arrear.getTotalMoney());//水费
			chgFeesPage.setPenalty(arrear.getPenalty());//违约金
			chgFeesPage.setWuMoney(arrear.getWuMoney());//污水
			chgFeesPage.setAlienMoney(arrear.getAlienMoney());//杂项费用
			chgFeesPage.setJiMoney(arrear.getJiMoney());//季加
			chgFeesPage.setJyMoney(arrear.getJyMoney());//二加压
			chgFeesPage.setLjMoney(arrear.getLjMoney());//垃圾费
			chgFeesPage.setDerateMoney(arrear.getDerateMoney());// 减免费用

			chgFeesPage.setPreBalance(pre_balance);//上次余额
			//实欠=欠费-已收
			BigDecimal realArrearMoney = arrear.getArrearMoney().subtract(arrear.getRecivedMoney());
			if (balance.doubleValue() < realArrearMoney.doubleValue()) {
//				chgFeesPage.setFeeChargeType("2");//收费方式1,全部收费,2部分收费,3余额预存（收费剩下）
//				chgFeesPage.setMoney(balance);//该笔欠费金额
//				balance = balance.subtract(balance);

				//不允许部分收费-退出继续
				log.warn(chgFeesPage.getCusId()+"余额不足，不允许部分收费");
				return Result.error("不允许部分收费");
			} else {
				chgFeesPage.setFeeChargeType("1");
				chgFeesPage.setMoney(realArrearMoney);//该笔欠费金额
				balance = balance.subtract(realArrearMoney);
			}
			//本次结余
			chgFeesPage.setPostBalance(balance);
			chgFeesPage.setRecivedMoney(new BigDecimal(0.0));//实收=0
			chgFeesPage.setStoredPaymentMoney(chgFeesPage.getMoney());//用预存余额缴费的,
			pre_balance=balance;

			chgFeesPage.setRemark("预存自动扣费");
			chgFeesPage.setStatus(1);
			chgFeesPage.setPaymentId(null);
			chgFeesPage.setBatchNo(batchNo + "" + index);

			//欠费明细
			List<ChgSubArrear> subArrearList = subArrearService.selectByMainId(arrear.getId());
			//当前已可收费用
			BigDecimal currFees = new BigDecimal(0.0);
			for (ChgSubArrear subArrear : subArrearList) {
				if (balance2.doubleValue() > 0) {
					ChgSubFees subFees = new ChgSubFees();
					subFees.setNatureId(subArrear.getNatureId());
					subFees.setPriceId(subArrear.getPriceId());
					subFees.setPrice(subArrear.getPrice());
					subFees.setItemCode(subArrear.getItemCode());
					subFees.setSubExpenseId(subArrear.getSubExpenseId());
					subFees.setAmount(subArrear.getAmount());
					subFees.setTierNo(subArrear.getTierNo());

					if (balance2.doubleValue() > subArrear.getArrearMoney().doubleValue()) {
						subFees.setMoney(subArrear.getMoney());
						balance2 = balance2.subtract(subArrear.getMoney());
					} else {
						subFees.setMoney(balance2);
						balance2 = balance2.subtract(subArrear.getMoney());
					}
					currFees = currFees.add(subFees.getMoney());
					subFees.setVatMoney(subArrear.getVatMoney());
					subFees.setDerateMoney(subArrear.getDerateMoney());
					chgSubFeesLs.add(subFees);

					HisSubArrear hisSubArrear = new HisSubArrear();
					BeanUtils.copyProperties(subArrear, hisSubArrear);
					hisSubArrear.setId(null);
					chgHisSubFeesLs.add(hisSubArrear);
				}
			}

			chgFeesPage.setChgSubFeesList(chgSubFeesLs);

			ChgFees chgFees = new ChgFees();
			BeanUtils.copyProperties(chgFeesPage, chgFees);
			feesService.saveMain(chgFees, chgFeesPage.getChgSubFeesList());

			if (currFees.doubleValue() > 0) {

				/**3余额记录*/
				if (chgFeesPage.getMoney().doubleValue() > 0) {
					ChgStoreds storedFee = new ChgStoreds();
					storedFee.setAccCode(arrear.getAccCode());
					storedFee.setAccName(arrear.getAccName());
					storedFee.setAccountId(arrear.getAccId());
					storedFee.setChargeId(chgFees.getId());
					//storedFee.setPaymentId(null);
					storedFee.setBatchNo(batchNo + "" + index);
					storedFee.setFeeStruckStatus("1");
					storedFee.setFeeTargetType("5");//缴费类型 1-收费,2-缴费,3-退费，4预存 5预存扣费
					storedFee.setFinancialDate(chgFeesPage.getFinancialDate());
					storedFee.setFinancialMonth(chgFeesPage.getFinancialMonth());
					storedFee.setStatus(1);
					storedFee.setRemark("预存自动扣费");

					storedFee.setPreBalance(chgFeesPage.getPreBalance());
					storedFee.setMoney(chgFeesPage.getMoney());
					storedFee.setPostBalance(chgFeesPage.getPostBalance());

					storedFee.setChargeTime(DateUtils.getDate("yyyy-MM-dd HH:mm:ss"));
					storedFee.setCashierId("sysStoredUser");
					storedsService.save(storedFee);
				}

				if (chgFeesPage.getMoney().doubleValue() == realArrearMoney.doubleValue()) {
					/**4.对应的欠费记录删除，欠费历史增加*/
					HisArrearsPage hisArrearsPage = new HisArrearsPage();
					BeanUtils.copyProperties(arrear, hisArrearsPage);
					hisArrearsPage.setId(null);
					hisArrearsPage.setHisSubArrearList(chgHisSubFeesLs);

					HisArrears hisArrears = new HisArrears();
					BeanUtils.copyProperties(hisArrearsPage, hisArrears);
					hisArrears.setFeeId(chgFees.getId());
					hisArrearsService.saveMain(hisArrears, hisArrearsPage.getHisSubArrearList());

					List<ChgArrearExpenses> arrearExpensesList = chgArrearExpensesService.list(
							new LambdaQueryWrapper<ChgArrearExpenses>()
									.eq(ChgArrearExpenses::getArrearId, arrear.getId())
									.eq(ChgArrearExpenses::getDelFlag, 0));

					if (null != arrearExpensesList && arrearExpensesList.size() > 0) {
						for (ChgArrearExpenses arrearExpenses : arrearExpensesList) {
							HisArrearExpenses harrearExpenses = new HisArrearExpenses();
							BeanUtils.copyProperties(arrearExpenses, harrearExpenses);
							harrearExpenses.setId(null);
							hisArrearExpensesService.save(harrearExpenses);
						}
					}

					arrearsService.delAlienSubByMainId(arrear.getId());
					arrearsService.delMain(arrear.getId());
				} else {
					//部分收费
					arrear.setRecivedMoney(currFees);
					arrearsService.updateById(arrear);
				}
			}
			/**5.缴费账户余额变化*/

			//实付=付款-找零
			//BigDecimal real = chargeFeeVo.getPayFee().realArrearMoney(chargeFeeVo.getZeroFee());

			accountService.update(new LambdaUpdateWrapper<ArcAccount>()
					.set(ArcAccount::getBalance, balance)
					.eq(ArcAccount::getId, arcAccount.getId()));

			return Result.OK(rsObject);
		}
		return Result.OK("OK");
	}


	@Override
	public Result<?> keyUniteCharge(ChgChargeFeeVo chargeFeeVo) {
		LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
		if(redisUtil.hasKey(sysUser.getRelTenantIds()+"_oneKeyFee")){
			return Result.error("请不要短时间内再使用【一键系统扣费】");
		}
		redisUtil.set(sysUser.getRelTenantIds()+"_oneKeyFee",DateUtils.getDate(),30*60);
		List<ChgArrears> arrearAutoPayList = arrearsService.getArrearAutoPayList();
		StringBuffer sb=new StringBuffer();
		if(null != arrearAutoPayList && arrearAutoPayList.size()>0){
			for (ChgArrears chgArrears : arrearAutoPayList) {
				Result<?> result = storedCharge(chgArrears);
				if(!result.isSuccess()){
					sb.append(chgArrears.getCusId()+" "+result.getMessage()+";");
//					return result;
				}
			}
		}
		if(sb.length()>2){
			return Result.OK("这些用户扣费异常："+sb.toString());
		}
		return Result.OK("扣费成功");
	}

	@Override
	public Result<?> indexData(ChgChargeFeeVo chargeFeeVo,LoginUser loginUser) {

		/**
		 * 1、总开户0今日开户0总销户0今日销户0总报停户数0今日报停0总停水户数0今日停水0
		 * 2、您本月已抄表0 抄表水量 0  本月未抄表0
		 * 3、 您目前有 0 条抄表记录等待审核 今日审核0 条
		 * 4、今日水费相关减免0 笔减免金额 0 元 今日杂项费用减免0 笔减免金额 0 元
		 * 5、今日已开收据0 笔票据金额 0 元  今日已开发票0 笔票据金额 0 元
		 * 6、总笔数0 笔金额 0 元 窗口退费0 笔金额 0 元 窗口现金0 笔金额 0 元
		 * 		窗口扫码0 笔金额 0 元 微信0 笔金额 0 元 预存扣费 笔 金额 元 银行代收 笔金额 元
		 *
		 * 用户状态 1正常2报停3停水4销户 waterUserStatus
		 *  arcCustomersService
		 * */
		LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();

		if( null == sysUser){
			if(null == loginUser){
				return Result.OK("系统自动不需要设置首页数据更新");
			}
			sysUser=loginUser;
			TenantContext.setTenant(sysUser.getRelTenantIds().split(",")[0]);
		}

		JSONObject dataJson=new JSONObject();

		//水表用户数据、已抄未抄数据
		ArcIndexDataVO arcVo=null;
		List<ArcIndexDataVO> arcIndexDataVOS = arcCustomersService.queryArcIndexData();
		if(null != arcIndexDataVOS && arcIndexDataVOS.size()>0 &&  !"[null]".equals(arcIndexDataVOS.toString())){
			arcVo = arcIndexDataVOS.get(0);
			if(null != arcVo){
				arcVo.setOpenNum(arcVo.getNormalNum());
				dataJson.put("dataAcc",arcVo);
			}
		}else{
			arcVo=new ArcIndexDataVO();
			arcVo.setOpenNum(0);
			arcVo.setCancelNum(0);
			arcVo.setNormalNum(0);
			arcVo.setStopNum(0);
			arcVo.setNormalNum(0);
			arcVo.setTodayCance(0);
			arcVo.setTodayNotice(0);
			arcVo.setTodayStop(0);
			arcVo.setTodayCance(0);
			arcVo.setUnreadNum(0);
			arcVo.setReadNum(0);
			dataJson.put("dataAcc",arcVo);
		}

		//抄表水量 审核数待审数
		List<MrIndexDataVO> mrIndexDataVOS = mrRecordsService.queryMrIndexDataAccount();
		List<MrIndexDataVO> mrIndexDataVOS1 = mrRecordsService.queryMrIndexDataAudit();
		if(null != mrIndexDataVOS1 && mrIndexDataVOS1.size()>0){
			MrIndexDataVO indexDataVO = mrIndexDataVOS1.get(0);
			if(null != mrIndexDataVOS && mrIndexDataVOS.size()>0){
				MrIndexDataVO dataVO = mrIndexDataVOS.get(0);
				if(null != dataVO) {
					indexDataVO.setReadAccount(dataVO.getReadAccount());
				}
			}
			dataJson.put("dataRecord",indexDataVO);
		}else{
			MrIndexDataVO dataVO = new MrIndexDataVO();
			dataVO.setReadAccount(new BigDecimal(0));
			dataVO.setPendingNum(0);
			dataVO.setTodayAudit(0);
			dataJson.put("dataRecord",dataVO);
		}

		List<ChgIndexDataDerateVO> chgIndexDataDerateVOS = storedsService.queryChgIndexDataDerate();
		if(null != chgIndexDataDerateVOS && chgIndexDataDerateVOS.size()>0){
			dataJson.put("dataDerate",chgIndexDataDerateVOS.get(0));
		}else{
			ChgIndexDataDerateVO derateVO = new ChgIndexDataDerateVO();
			derateVO.setAlienFee(new BigDecimal(0));
			derateVO.setAlienNum(0);
			derateVO.setWaterFee(new BigDecimal(0));
			derateVO.setWaterNum(0);
			dataJson.put("dataDerate",derateVO);
		}
		List<ChgIndexDataFeeVO> chgIndexDataFeeVOS = storedsService.queryChgIndexDataFee();
		if(null != chgIndexDataFeeVOS && chgIndexDataFeeVOS.size()>0
				&& !"[null]".equals(chgIndexDataFeeVOS.toString().toLowerCase())){
			ChgIndexDataFeeVO dataFeeVO = chgIndexDataFeeVOS.get(0);

			dataFeeVO.setTodayNum(dataFeeVO.getBankNum()+dataFeeVO.getCashNum()
					+dataFeeVO.getReturnNum()+dataFeeVO.getScanNum()
					+dataFeeVO.getStoreNum()+dataFeeVO.getWxNum());
			dataFeeVO.setTodayFee(dataFeeVO.getCashFee().add(dataFeeVO.getBankFee())
					.add(dataFeeVO.getScanFee()).add(dataFeeVO.getStoreFee())
					.add(dataFeeVO.getWxFee()).subtract(dataFeeVO.getReturnFee()));
			dataJson.put("dataFee",dataFeeVO);
		}else{
			ChgIndexDataFeeVO derateVO = new ChgIndexDataFeeVO();
			derateVO.setBankFee(new BigDecimal(0));
			derateVO.setBankNum(0);
			derateVO.setCashFee(new BigDecimal(0));
			derateVO.setCashNum(0);
			derateVO.setScanFee(new BigDecimal(0));
			derateVO.setScanNum(0);
			derateVO.setWxFee(new BigDecimal(0));
			derateVO.setWxNum(0);

			derateVO.setTodayFee(new BigDecimal(0));
			derateVO.setTodayNum(0);
			derateVO.setReturnFee(new BigDecimal(0));
			derateVO.setReturnNum(0);
			derateVO.setStoreCount(0);
			derateVO.setStoreFee(new BigDecimal(0));
			derateVO.setStoreMoney(new BigDecimal(0));
			derateVO.setStoreNum(0);

			dataJson.put("dataFee",derateVO);
		}

		List<BvIndexDataVO> bvIndexDataVOS = bvVouchersService.queryBvIndexData();
		if(null != bvIndexDataVOS && bvIndexDataVOS.size()>0){
			dataJson.put("dataVoucher",bvIndexDataVOS.get(0));
		}else{
			BvIndexDataVO dataVO = new BvIndexDataVO();
			dataVO.setBillFee(new BigDecimal(0));
			dataVO.setBillNum(0);
			dataVO.setReceiptFee(new BigDecimal(0));
			dataVO.setReceiptNum(0);
			dataJson.put("dataVoucher",dataVO);
		}
		String[] userIds = new String[1];
		userIds[0]=sysUser.getId();
		redisUtil.set(sysUser.getId()+"_indexData",JSONObject.parse(dataJson.toJSONString()),24*60*60);

		baseAPI.sendWebSocketMsg(userIds,"indexData",(JSONObject)JSONObject.parse(dataJson.toJSONString()));
		return Result.OK();
	}

	@Override
	public void feePrePayOrderState() {
		List<ChgPayments> chgPayments = paymentsService.selectPrePayOrder(null,null);
		if(null != chgPayments && chgPayments.size()>0){
			for (ChgPayments payment : chgPayments) {
				ChgChargeFeeVo chargeFeeVo = new ChgChargeFeeVo();
				chargeFeeVo.setAccCode(payment.getAccCode());
				//chargeFeeVo.setId(cusVO.getId());
				//chargeFeeVo.setAccName(cusVO.getAccName());
				chargeFeeVo.setFeePayWay("3");//支付方式 3微信
				chargeFeeVo.setFeeTollWay("3");//收费方式 3余额预存（收费剩下）
				chargeFeeVo.setFeeWholeWay("01");//整收方式 实收
				//paymentsPage.setBillTypeId(null);//票据类型
				//paymentsPage.setFeePrintWay(null);//打印方式
				chargeFeeVo.setPayFee(payment.getPayFee());//实付
				//chargeFeeVo.setReceFee(payment.ge);//应缴
				chargeFeeVo.setZeroFee(new BigDecimal(0).setScale(0,BigDecimal.ROUND_HALF_UP));//找零

				//this.mpCharge(feevo,payments,arrarIds);
			}
		}



	}

	/**设置首页数据动态更新*/
	@Override
	public void setIndexData(String type,String key,Object val,Boolean isSend){
		LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
		JSONObject dataJson = (JSONObject) redisUtil.get(sysUser.getId() + "_indexData");
		if(null != dataJson) {

			JSONObject typeObj = (JSONObject) dataJson.get(type);

			if("pendingNum".equals(key)){
				//待审是减少
				Integer integer = typeObj.getInteger(key);
				if(null !=integer){
					integer = integer- (Integer) val;
					typeObj.put(key, integer);
				}
			}else if (val instanceof Integer) {
				Integer v = typeObj.getInteger(key);
				if(null != v){
					v = v + (Integer) val;
					typeObj.put(key, v);
				}else{
					typeObj.put(key, val);
				}
			} else if (val instanceof BigDecimal) {
				BigDecimal v = typeObj.getBigDecimal(key);
				if(null != v){
					v = v.add((BigDecimal) val);
					typeObj.put(key, v);
				}else {
					typeObj.put(key, val);
				}
			}
			dataJson.put(type, typeObj);
			redisUtil.set(sysUser.getId() + "_indexData", dataJson, 24 * 60 * 60 );
			if(isSend){
				if("dataRecord".equals(type)){
					List<ArcIndexDataVO> arcIndexDataVOS = arcCustomersService.queryArcIndexData();
					if(null != arcIndexDataVOS && arcIndexDataVOS.size()>0){
						dataJson.put("dataAcc",arcIndexDataVOS.get(0));
					}
				}
				String[] userIds = new String[1];
				userIds[0] = sysUser.getId();
				baseAPI.sendWebSocketMsg(userIds, "indexData", dataJson);
			}
		}else{
			this.indexData(null,null);
		}
	}

	/**
	 * 取消收费-都是当月
	 */
	@Override
	@Transactional
	public Result<?> cancelCharge(ChgChargeFeeVo cancelFeeVo) {

		/**
		 * 缴费记录只跟收支有关
		 * 如果本月缴费了两笔，取消最后第二笔，，需要验证是否存在下级业务
		 *
		 * accountId 缴费账户ID
		 * charge[] chargeId 收费ID
		 * case "冲减原因"
		 * approverName 冲红审批人
		 *
		 * 1. 是否是当前月份
		 * 2. 是否是冲红
		 * 3. 是否缴费扣费（是否一笔缴费多笔收费）
		 * 4. 是否系统自动扣费
		 * 5. 是否涉及账号金额变动
		 *
		 */

		String [] feeIds = cancelFeeVo.getFeeIds().split(",");
		LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
		List<ChgFees> chgChargeLs = feesService.listByIds(Arrays.asList(feeIds));
		ArcAccount arcAccount=null;
		ArcAccountCusVO accountCusVO=null;
		if( null != chgChargeLs && chgChargeLs.size()>0){

			String cusId = chgChargeLs.get(0).getCusId();
			String accId =null;

			List<ArcAccountMeter> aamLs = arcAccountMeterService.list(new QueryWrapper<ArcAccountMeter>()
					.lambda().eq(ArcAccountMeter::getCusId, cusId));
			if(null != aamLs && aamLs.size()>0){
				//根据水表-查询主缴费账号
				accId = aamLs.get(0).getAccountId();
				arcAccount = accountService.getById(accId);
				if (null == arcAccount) {
					//缴费账户不存在
					return Result.error("缴费账户不存在");
				}
			}else {
				List<ArcAccountCusVO> cusVOList = accountService.queryAccount(null, null, cusId);
				if( null != cusVOList && cusVOList.size()>0){
					accountCusVO=cusVOList.get(0);
					accId = cusVOList.get(0).getId();
					arcAccount = accountService.getById(accId);
					if (null == arcAccount) {
						//缴费账户不存在
						return Result.error("缴费账户不存在");
					}
				}
			}
		}

		BasePeriod basePeriod = basePeriodService.getOne(
				new LambdaQueryWrapper<BasePeriod>().eq(BasePeriod::getIsUsed, 1));

		//当前收费退费的缴费ID
		Set<String>payIdSet=new HashSet<>();
		//系统扣费的取消记录
		List<ChgFees>sysAutoFeeLs=new ArrayList<>();
		for (ChgFees chgCharge : chgChargeLs) {
			String paymentId = chgCharge.getPaymentId();
			if(oConvertUtils.isNotEmpty(paymentId)){
				if(!payIdSet.contains(paymentId)){
					payIdSet.add(paymentId);
				}
			}else {
				//系统自动扣费
				if("4".equals(chgCharge.getFeePayWay())){
					sysAutoFeeLs.add(chgCharge);
				}
			}
		}

		//账户余额
		BigDecimal balance = arcAccount.getBalance();
		//本次取消后还原上次余额
		BigDecimal ben_balance = new BigDecimal(0.0);
		//欠费金额
		BigDecimal arrearMoney =new BigDecimal(0.0);

		/**3. 是否缴费扣费（是否一笔缴费多笔收费,是否使用余额）*/
		for (String payId : payIdSet) {
			ChgPayments payments = paymentsService.getById(payId);

			/**是否本次缴费之后还有新的*/
			int count = paymentsService.count(new QueryWrapper<ChgPayments>().lambda()
					.gt(ChgPayments::getFinancialDate, payments.getFinancialDate())//财务日期大于
					.eq(ChgPayments::getDelFlag, 0)
					.eq(ChgPayments::getAccountId, payments.getAccountId())
					.eq(ChgPayments::getStatus, 1)
					.ne(ChgPayments::getId,payments.getId()));
			if(count>0){
				return Result.error("请先取消最新一笔的缴费");
			}

			List<ChgFees> payFeelist = feesService.list(new QueryWrapper<ChgFees>().lambda()
					.eq(ChgFees::getPaymentId, payId)
					.eq(ChgFees::getDelFlag, 0)
					.eq(ChgFees::getStatus, 1));
			if(null != payFeelist && payFeelist.size()>0){
				for (ChgFees chgCharge : payFeelist) {
					if (basePeriod.getMonth().equals(chgCharge.getFinancialMonth())) {
						//预存记录无效
						storedsService.update(new LambdaUpdateWrapper<ChgStoreds>()
							.set(ChgStoreds::getStatus,2) //取消
							.eq(ChgStoreds::getFeeStruckStatus, "1") //冲红状态是被冲帐
							.eq(ChgStoreds::getChargeId, chgCharge.getId())
							.eq(ChgStoreds::getDelFlag, 0)
							.eq(ChgStoreds::getStatus, "1") );
						//收费金额
						arrearMoney= arrearMoney.add(chgCharge.getMoney().subtract(chgCharge.getRecivedMoney()));
						/**收费取消作为无效即可*/
						feesService.update(new LambdaUpdateWrapper<ChgFees>()
								.set(ChgFees::getStatus, "0")
								.set(ChgFees::getRemark, "取消收费")
								.eq(ChgFees::getId, chgCharge.getId()));

						subFeesService.update(new LambdaUpdateWrapper<ChgSubFees>()
								.set(ChgSubFees::getDelFlag, 1)
								.eq(ChgSubFees::getChargeId, chgCharge.getId()));

						//历史欠费记录
						List<HisArrears> hisArrearsList = hisArrearsService.list(
								new LambdaQueryWrapper<HisArrears>()
										.eq(HisArrears::getFeeId, chgCharge.getId()));
						/**恢复欠费记录*/
						for (HisArrears hisArrears : hisArrearsList) {
							List<ChgSubArrear> subArrearList = new ArrayList<>();
							List<HisSubArrear> hisSubArrears = hisSubArrearsService.selectByMainId(hisArrears.getId());
							for (HisSubArrear hisSubArrear : hisSubArrears) {
								ChgSubArrear subArrear = new ChgSubArrear();
								BeanUtils.copyProperties(hisSubArrear, subArrear);
								subArrearList.add(subArrear);
							}
							ChgArrears chgArrears = new ChgArrears();
							BeanUtils.copyProperties(hisArrears, chgArrears);
							chgArrears.setId(hisArrears.getOldArrId());
							arrearsService.saveMain(chgArrears, subArrearList,"1");

							//历史欠费记录-删除
							hisArrearsService.delMain(hisArrears.getId());
						}
					} else {
						throw new JeecgBootException("不允许跨月取消");
					}
				}
				//缴费记录无效
				paymentsService.update(new LambdaUpdateWrapper<ChgPayments>()
						.set(ChgPayments::getStatus,2) //取消
						.set(ChgPayments::getRemark,"取消收费")
						.eq(ChgPayments::getDelFlag, 0)
						.eq(ChgPayments::getStatus, "1")
						.eq(ChgPayments::getId, payId)// 缴费类型 是1扣费的
				);

				/**取消都是，从最后一个月开始取消，所以上次余额，即为账号余额*/
				accountService.update(new LambdaUpdateWrapper<ArcAccount>()
						.set(ArcAccount::getBalance, payments.getPreMoney())
						.eq(ArcAccount::getId, arcAccount.getId()));
			}
		}
		/**4. 是否系统自动扣费*/
		if(null != sysAutoFeeLs && sysAutoFeeLs.size()>0){
			//系统扣费取消是需要账号余额增加取消金额
			for (ChgFees chgCharge : sysAutoFeeLs) {
				if (basePeriod.getMonth().equals(chgCharge.getFinancialMonth())) {
					//预存记录无效
					storedsService.update(new LambdaUpdateWrapper<ChgStoreds>()
							.set(ChgStoreds::getStatus,2) //取消
							.eq(ChgStoreds::getFeeStruckStatus, "1") //冲红状态是被冲帐
							.eq(ChgStoreds::getChargeId, chgCharge.getId())
							.eq(ChgStoreds::getDelFlag, 0)
							.eq(ChgStoreds::getStatus, "1") );

					arrearMoney= arrearMoney.add(chgCharge.getMoney().subtract(chgCharge.getRecivedMoney()));

					/**收费取消作为无效即可*/
					feesService.update(new LambdaUpdateWrapper<ChgFees>()
							.set(ChgFees::getStatus, "0")
							.set(ChgFees::getRemark, "取消收费")
							.eq(ChgFees::getId, chgCharge.getId()));

					subFeesService.update(new LambdaUpdateWrapper<ChgSubFees>()
							.set(ChgSubFees::getDelFlag, 1)
							.eq(ChgSubFees::getChargeId, chgCharge.getId()));

					//历史欠费记录
					List<HisArrears> hisArrearsList = hisArrearsService.list(
							new LambdaQueryWrapper<HisArrears>()
									.eq(HisArrears::getFeeId, chgCharge.getId()));
					/**恢复欠费记录*/
					for (HisArrears hisArrears : hisArrearsList) {
						List<ChgSubArrear> subArrearList = new ArrayList<>();
						List<HisSubArrear> hisSubArrears = hisSubArrearsService.selectByMainId(hisArrears.getId());
						for (HisSubArrear hisSubArrear : hisSubArrears) {
							ChgSubArrear subArrear = new ChgSubArrear();
							BeanUtils.copyProperties(hisSubArrear, subArrear);
							subArrearList.add(subArrear);
						}
						ChgArrears chgArrears = new ChgArrears();
						BeanUtils.copyProperties(hisArrears, chgArrears);
						chgArrears.setId(hisArrears.getOldArrId());
						arrearsService.saveMain(chgArrears, subArrearList,"1");

						//历史欠费记录-删除
						hisArrearsService.delMain(hisArrears.getId());
					}
				} else {
					throw new JeecgBootException("不允许跨月取消");
				}
			}
			//最后余额=现在余额+欠费
			balance=balance.add(arrearMoney);
			/**5.缴费账户余额变化*/
			if (arcAccount.getBalance().doubleValue() != balance.doubleValue()) {
				accountService.update(new LambdaUpdateWrapper<ArcAccount>()
						.set(ArcAccount::getBalance, balance)
						.eq(ArcAccount::getId, arcAccount.getId()));
			}
		}
		///**设置首页数据动态更新*/
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					/**设置首页数据动态更新-退费*/
					indexData(null,null);
				} catch (Exception e) {
					e.printStackTrace();
				} finally {
					log.warn("首页数据动态更新");
				}
			}
		}).start();

		return Result.OK("取消成功");
	}
	/**
	 * 根据缴费取消收费
	 */
	@Override
	@Transactional
	public Result<?> cancelChargeByPay(ChgPayments chgPayments) {

		/**
		 * 缴费记录只跟收支有关 -- 农行收费取消原路返回，余额是有变动的，要还原
		 *
		 *
		 */
		ArcAccount arcAccount=accountService.getById(chgPayments.getAccountId());
		if (null == arcAccount) {
			//缴费账户不存在
			return Result.error("缴费账户不存在");
		}
		BasePeriod basePeriod = basePeriodService.getOne(
				new LambdaQueryWrapper<BasePeriod>().eq(BasePeriod::getIsUsed, 1));

		LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
		//账户余额
		BigDecimal balance = arcAccount.getBalance();
		//欠费金额
		BigDecimal arrearMoney =new BigDecimal(0.0);

		/**3. 是否缴费扣费（是否一笔缴费多笔收费）*/
		List<ChgFees> payFeelist = feesService.list(new QueryWrapper<ChgFees>().lambda()
				.eq(ChgFees::getPaymentId, chgPayments.getId())
				.eq(ChgFees::getDelFlag, 0)
				.eq(ChgFees::getStatus, 1));
		if(null != payFeelist && payFeelist.size()>0){
			for (ChgFees chgCharge : payFeelist) {
				if (basePeriod.getMonth().equals(chgCharge.getFinancialMonth())) {
					//预存记录无效
					storedsService.update(new LambdaUpdateWrapper<ChgStoreds>()
						.set(ChgStoreds::getStatus,2) //取消
						.eq(ChgStoreds::getFeeStruckStatus, "1") //冲红状态是被冲帐
						.eq(ChgStoreds::getChargeId, chgCharge.getId())
						.eq(ChgStoreds::getDelFlag, 0)
						.eq(ChgStoreds::getStatus, "1") );

					/**收费取消作为无效即可*/
					feesService.update(new LambdaUpdateWrapper<ChgFees>()
							.set(ChgFees::getStatus, "0")
							.set(ChgFees::getRemark, "取消收费")
							.eq(ChgFees::getId, chgCharge.getId()));

					subFeesService.update(new LambdaUpdateWrapper<ChgSubFees>()
							.set(ChgSubFees::getDelFlag, 1)
							.eq(ChgSubFees::getChargeId, chgCharge.getId()));

					//历史欠费记录
					List<HisArrears> hisArrearsList = hisArrearsService.list(
							new LambdaQueryWrapper<HisArrears>()
									.eq(HisArrears::getFeeId, chgCharge.getId()));
					/**恢复欠费记录*/
					for (HisArrears hisArrears : hisArrearsList) {
						List<ChgSubArrear> subArrearList = new ArrayList<>();
						List<HisSubArrear> hisSubArrears = hisSubArrearsService.selectByMainId(hisArrears.getId());
						for (HisSubArrear hisSubArrear : hisSubArrears) {
							ChgSubArrear subArrear = new ChgSubArrear();
							BeanUtils.copyProperties(hisSubArrear, subArrear);
							subArrearList.add(subArrear);
						}
						ChgArrears chgArrears = new ChgArrears();
						BeanUtils.copyProperties(hisArrears, chgArrears);
						chgArrears.setId(hisArrears.getOldArrId());
						arrearsService.saveMain(chgArrears, subArrearList,"1");

						//历史欠费记录-删除
						hisArrearsService.delMain(hisArrears.getId());
					}
				} else {
					throw new JeecgBootException("不允许跨月取消");
				}
			}
			//缴费记录无效
			paymentsService.update(new LambdaUpdateWrapper<ChgPayments>()
					.set(ChgPayments::getStatus,2) //取消
					.set(ChgPayments::getRemark,"根据缴费取消收费")
					.eq(ChgPayments::getDelFlag, 0)
					.eq(ChgPayments::getStatus, "1")
					.eq(ChgPayments::getId, chgPayments.getId()) );

			accountService.update(new LambdaUpdateWrapper<ArcAccount>()
					.set(ArcAccount::getBalance, chgPayments.getPreMoney())
					.set(ArcAccount::getUpdateTime,new Date())
					.set(ArcAccount::getUpdateBy,sysUser.getUsername())
					.eq(ArcAccount::getId, arcAccount.getId()));
		}else{
			//充值取消的

			//预存记录无效
			storedsService.update(new LambdaUpdateWrapper<ChgStoreds>()
					.set(ChgStoreds::getStatus,2) //取消
					.eq(ChgStoreds::getFeeStruckStatus, "1") //冲红状态是被冲帐
					.eq(ChgStoreds::getPaymentId, chgPayments.getId())
					.eq(ChgStoreds::getDelFlag, 0)
					.eq(ChgStoreds::getStatus, "1") );

			//缴费记录无效
			paymentsService.update(new LambdaUpdateWrapper<ChgPayments>()
					.set(ChgPayments::getStatus,2) //取消
					.set(ChgPayments::getRemark,"根据缴费取消收费")
					.eq(ChgPayments::getDelFlag, 0)
					.eq(ChgPayments::getStatus, "1")
					.set(ChgPayments::getUpdateTime,new Date())//更新时间
					.set(ChgPayments::getUpdateBy,sysUser.getUsername())
					.eq(ChgPayments::getId, chgPayments.getId()) );

			accountService.update(new LambdaUpdateWrapper<ArcAccount>()
					.set(ArcAccount::getBalance, chgPayments.getPreMoney())
					.set(ArcAccount::getUpdateTime,new Date())
					.set(ArcAccount::getUpdateBy,sysUser.getUsername())
					.eq(ArcAccount::getId, arcAccount.getId()));

		}


		///**设置首页数据动态更新*/
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					/**设置首页数据动态更新-退费*/
					indexData(null,null);
				} catch (Exception e) {
					e.printStackTrace();
				} finally {
					log.warn("首页数据动态更新");
				}
			}
		}).start();

		return Result.OK("取消成功");
	}

	@Override
	@Transactional
	public Result<?> printBillSubmit(JSONObject billData,List<ChgFeePrintVo> feePrintvoLs) {

		/***
		 * billId
		 * accountId
		 * paymentId
		 * billTypeId
		 * feePrintWay
		 * printIndex
		 * isPrint
		 * isNew 新开/重打
		 *
		 * 不管什么打印方式，当前只有打印一张票据 feePrintvo
		 * 这个printIndex是定位 当前打印哪一张 printBillData
		 *
		 *
		 */
		billData = (JSONObject) JSONObject.parse(JSON.toJSONString(billData));
		String billId = billData.getString("billId");
		String accountId = billData.getString("accountId");
		Integer printIndex = billData.getInteger("printIndex");
		Boolean isPrint = billData.getBoolean("isPrint");
		Boolean isNew = billData.getBoolean("isNew");
		if(isPrint){
			//确认已打印
			if(isNew) {
				//Set<String> cusIdSet = new HashSet();
				ChgFeePrintVo feePrintvo = null;
				JSONArray feesArray = null;

				if(null != feePrintvoLs && feePrintvoLs.size()>0){
					feePrintvo = feePrintvoLs.get(printIndex);
				}

				BvVouchers vouchers = bvVouchersService.getById(billId);
				vouchers.setBillStatusId("03");
				//ChgPayments payments = paymentsService.getById(vouchers.getPaymentId());
				//JSONObject userFeeIdJson = getFeeListByPayments(vouchers.getPaymentId());
				////缴费账户对应 用户水表信息
				//List<ArcAccountCusVO> cusVOList = accountService.queryAccount(payments.getAccountId()
				//		, null,null);

				List<BvSubVouchers> subVouchersLs = new ArrayList<>();
				BvSubVouchers subVouchers = new BvSubVouchers();
				subVouchers.setAmount(new BigDecimal(0));
				subVouchers.setMoney(new BigDecimal(0));
				subVouchers.setChargeId(feePrintvo.getFeeId());
				subVouchers.setAccountId(accountId);
				subVouchers.setPrintJson(JSON.toJSONString(feePrintvo));
				subVouchersLs.add(subVouchers);

				for (BvSubVouchers subVoucher : subVouchersLs) {
					subVoucher.setVoucherId(vouchers.getId());
					subVouchersService.save(subVoucher);
				}
				bvVouchersService.updateById(vouchers);
			}else{
				//重打仅增加打印次数
				BvVouchers vouchers = bvVouchersService.getById(billId);
				vouchers.setReprintTimes(vouchers.getReprintTimes()+1);
				bvVouchersService.updateById(vouchers);
			}
		}else{
			if(null != isNew && isNew) {
				BvVouchers vouchers = bvVouchersService.getById(billId);
				vouchers.setBillStatusId("01");
				vouchers.setFinancialDate(null);
				vouchers.setBillPrintType("");
				vouchers.setMoney(new BigDecimal(0.0));
				vouchers.setOperatedTime(null);
				vouchers.setPaymentId("");
				vouchers.setOperatorId("");
				bvVouchersService.updateById(vouchers);

				List<BvSubVouchers> subVouchers = subVouchersService.selectByMainId(vouchers.getId());
				if (null != subVouchers && subVouchers.size() > 0) {
					List<String> collect = subVouchers.stream().map(BvSubVouchers::getId).collect(Collectors.toList());
					subVouchersService.removeByIds(collect);
				}
			}
			//else{
			// //无需操作
			//}
		}
		return Result.OK("已打印成功");
	}

	//退费
	@Override
	@Transactional
	public Result<?> returnFee(ChgChargeFeeVo chargeFeeVo) {

		//缴费账户
		ArcAccount arcAccount = accountService.getById(chargeFeeVo.getId());
		//账户余额
		BigDecimal balance = arcAccount.getBalance();
		BigDecimal reFee = chargeFeeVo.getReFee();

		BigDecimal subtract = balance.subtract(reFee);

		if(subtract.doubleValue()<0){
			return Result.error("余额不足");
		}
		BasePeriod basePeriod = basePeriodService.getOne(
				new LambdaQueryWrapper<BasePeriod>().eq(BasePeriod::getIsUsed, 1));
		LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
		ArcAccountCusVO accountCusVO=null;
		List<ArcAccountCusVO> cusVOList = accountService.queryAccount(arcAccount.getId(), null, null);
		if( null != cusVOList && cusVOList.size()>0) {
			accountCusVO = cusVOList.get(0);
		}

		ChgPayments chgPayments = new ChgPayments();
		chgPayments.setStatus(1);
		chgPayments.setFinancialMonth(basePeriod.getMonth());
		chgPayments.setFinancialDate(DateUtils.getDate("yyyy-MM-dd HH:mm:ss"));

		chgPayments.setPreMoney(arcAccount.getBalance());
		chgPayments.setMoney(reFee);
		chgPayments.setPostMoney(subtract);
		chgPayments.setPayFee(reFee);
		chgPayments.setSerialNo(DateUtils.getDate("yyyyMMddHHmmss"));

		chgPayments.setFeeTargetType("3");//退费
		chgPayments.setFeePayWay("4");//余额

		chgPayments.setAccountId(arcAccount.getId());
		chgPayments.setAccCode(arcAccount.getCode());
		chgPayments.setAccName(accountCusVO.getAccName());
		chgPayments.setFeeTollWay("01");//全部收费
		chgPayments.setFeeWholeWay("01");//实收
		chgPayments.setBillTypeId("01");//收据
		paymentsService.save(chgPayments);


		/**预存记录-增加*/
		ChgStoreds storeds = new ChgStoreds();
		storeds.setAccountId(arcAccount.getId());
		//storeds.setChargeId(chgCharge.getId());
		//storeds.setPaymentId(chgPayments.getId());
		//storeds.setBatchNo(batchNo+index);
		storeds.setAccCode(arcAccount.getCode());
		storeds.setAccName(accountCusVO.getAccName());

		storeds.setFeeStruckStatus("1");
		storeds.setFeeTargetType("3");//退费
		storeds.setFinancialDate(DateUtils.getDate("yyyy-MM-dd HH:mm:ss"));
		storeds.setFinancialMonth(basePeriod.getMonth());
		storeds.setStatus(1);
		storeds.setPreBalance(arcAccount.getBalance());
		storeds.setMoney(reFee);

		storeds.setPostBalance(subtract);
		storeds.setChargeTime(DateUtils.getDate("yyyy-MM-dd HH:mm:ss"));
		storeds.setCashierId(sysUser.getUsername());
		storedsService.save(storeds);

		accountService.update(new LambdaUpdateWrapper<ArcAccount>()
				.set(ArcAccount::getBalance, subtract)
				.eq(ArcAccount::getId, arcAccount.getId()));
		return Result.OK("退费成功");
	}

	@Override
	public List<ChgFees> noOpenBillFees(String paymentId) {
		return chgFeesMapper.noOpenBillFees(paymentId);
	}

	//补打-作废票据
	@Override
	public Result<?> printVoidBill(JSONObject billData) {
		String billId = billData.getString("id");
		BvVouchers vouchers = bvVouchersService.getById(billId);
		if(null == vouchers){
			return Result.error("票据不存在");
		}

		SysVarModel isPrintBill = baseAPI.querySysVar("is_print_bill");//是否打印收据
		if(null == isPrintBill || "0".equals(isPrintBill.getValue() )){
			return Result.OK("无打印收据");
		}

		//票据类型
		String billTypeId = vouchers.getBillTypeId();
		//打印方式
		String billPrintType = vouchers.getBillPrintType();
		if(!"03".equals(vouchers.getBillStatusId())){
			return Result.error("票据已不是有效，请重新查询开票");
		}

		vouchers.setBillStatusId("04");
		bvVouchersService.updateById(vouchers);

		JSONObject rsObj=new JSONObject();
		List<BvSubVouchers> subVouchersLs = subVouchersService.selectByMainId(billId);
		if(null != subVouchersLs && subVouchersLs.size()>0){
			BvSubVouchers subVouchers = subVouchersLs.get(0);
			String chargeId = subVouchers.getChargeId();
			ChgFees fees = feesService.getById(chargeId);
			rsObj.put("paymentId",fees.getPaymentId());
		}

		boolean update = subVouchersService.update(new LambdaUpdateWrapper<BvSubVouchers>()
				.set(BvSubVouchers::getDelFlag, 1)
				.eq(BvSubVouchers::getVoucherId, billId)
				.eq(BvSubVouchers::getDelFlag, 0));

		rsObj.put("billTypeId",billTypeId);
		rsObj.put("feePrintWay",billPrintType);
		return Result.OK(rsObj);
	}

	/**费用减免*/
	@Override
	@Transactional
	public Result<?> deratefeeBill(JSONObject billData) {
		String subArrearId = billData.getString("subArrearId");
		String arrearId = billData.getString("arrearId");
		String expenseId = billData.getString("expenseId");
		String subExpenseId = billData.getString("subExpenseId");
		String feeStrikeCause = billData.getString("feeStrikeCause");
		String responMan = billData.getString("responMan");
		String remark = billData.getString("remark");
		BigDecimal money = billData.getBigDecimal("money");

		ChgSubArrear subArrear = subArrearService.getById(subArrearId);
		if(null == subArrear){
			return Result.error("减免费用项不存在");
		}
		if(money.doubleValue() <= 0){
			return Result.error("减免金额不大于零！");
		}
		BigDecimal old_money = subArrear.getMoney();
		ChgDerate chgDerate = new ChgDerate();
		chgDerate.setMoney(money);

		subArrearService.update(new LambdaUpdateWrapper<ChgSubArrear>()
				.set(ChgSubArrear::getDerateMoney, subArrear.getDerateMoney().add( money))
				.set(ChgSubArrear::getMoney,subArrear.getMoney().subtract(money))
				.eq(ChgSubArrear::getId,subArrear.getId())
			);

		ChgArrears arrears = arrearsService.getById(arrearId);
		arrears.setDerateMoney(arrears.getDerateMoney().add(money));
		arrears.setMoney(arrears.getMoney().subtract(money));
		arrears.setArrearMoney(arrears.getArrearMoney().subtract(money));

		// if("03".equals(subArrear.getItemCode())){ // 01 水费 03 污水费
		// 	arrears.setWuMoney(arrears.getWuMoney().subtract(money));
		// }else if("01".equals(subArrear.getItemCode())){ // 01 水费 03 污水费
		// 	arrears.setTotalMoney(arrears.getTotalMoney().subtract(money));
		// }else if("07".equals(subArrear.getItemCode())){ // 01 水费 03 污水费 07 垃圾费
		// 	arrears.setLjMoney(arrears.getLjMoney().subtract(money));
		// }else if("02".equals(subArrear.getItemCode())){ // 01 水费 02 违约金 03 污水费 07 垃圾费
		// 	arrears.setPenalty(arrears.getPenalty().subtract(money));
		// }else if("02".equals(subArrear.getItemCode())){ // 01 水费 02 违约金 03 污水费 04 杂项费 07 垃圾费
		// 	arrears.setAlienMoney(arrears.getAlienMoney().subtract(money));
		// }
		arrearsService.updateById(arrears);

		BlSubExpenses subExpenses = blSubExpensesService.getById(subExpenseId);
		if(null != subExpenses){
			chgDerate.setOldMoney(subExpenses.getMoney());

			subExpenses.setDerateMoney(money);
			subExpenses.setMoney(subExpenses.getMoney().subtract(money));
			blSubExpensesService.updateById(subExpenses);
		}else{
			chgDerate.setOldMoney(old_money);
		}

		// 直接使用 旧金额-减免金额
		chgDerate.setNewMoney(chgDerate.getOldMoney().subtract(chgDerate.getMoney()));
		// 上面有更新不会返回到当前对象，
		// chgDerate.setNewMoney(subArrear.getMoney());

		BlExpenses expenses = blExpensesService.getById(expenseId);
		if(null != expenses){
			expenses.setDerateMoney(expenses.getDerateMoney().add(money));
			expenses.setMoney(expenses.getMoney().subtract(money));
			blExpensesService.updateById(expenses);
		}

		chgDerate.setExpenseId(expenseId);
		chgDerate.setSubExpenseId(subExpenseId);
		chgDerate.setFeeStrikeCause(feeStrikeCause);
		chgDerate.setItemCode(subArrear.getItemCode());

		chgDerate.setResponMan(responMan);
		chgDerate.setRemark(remark);
		chgDerateService.save(chgDerate);

		///**设置首页数据动态更新*/
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					/**设置首页数据动态更新-费用减免*/
					indexData(null,null);
				} catch (Exception e) {
					e.printStackTrace();
				} finally {
					log.warn("首页数据动态更新");
				}
			}
		}).start();

		return Result.OK("减免成功");
	}

	/**费用违约金减免*/
	@Override
	@Transactional
	public Result<?> deratePenalty(JSONObject billData) {
		String subArrearId = billData.getString("subArrearId");
		String arrearId = billData.getString("arrearId");
		String expenseId = billData.getString("expenseId");
		String subExpenseId = billData.getString("subExpenseId");
		String feeStrikeCause = billData.getString("feeStrikeCause");
		String responMan = billData.getString("responMan");
		String remark = billData.getString("remark");
		BigDecimal money = billData.getBigDecimal("money");

//		ChgSubArrear subArrear = subArrearService.getById(subArrearId);
//		if(null == subArrear){
//			return Result.error("减免费用项不存在");
//		}
		ChgArrears arrears = arrearsService.getById(arrearId);
		if(null == arrears){
			return Result.error("欠费不存在");
		}
		if(money.doubleValue() <= 0){
			return Result.error("减免金额不大于零！");
		}
		ChgDerate chgDerate = new ChgDerate();
		chgDerate.setMoney(money);

		//欠费明细没有违约金
//		subArrearService.update(new LambdaUpdateWrapper<ChgSubArrear>()
//				.set(ChgSubArrear::getDerateMoney,money)
//				.set(ChgSubArrear::getMoney,subArrear.getMoney().subtract(money))
//				.eq(ChgSubArrear::getId,subArrear.getId())
//			);


		chgDerate.setOldMoney(arrears.getPenalty());

		if(arrears.getPenalty().doubleValue()<=0){
			return Result.error("该笔欠费记录没有产生违约金！");
		}

		//减免项不能再增加，走专项 每天都计算的
		//arrears.setPenalty(arrears.getPenalty().subtract(money).setScale(2,BigDecimal.ROUND_HALF_UP));
		arrears.setDerateMoney(arrears.getDerateMoney().add(money));//
		arrears.setMoney(arrears.getMoney().subtract(money));
		arrears.setArrearMoney(arrears.getArrearMoney().subtract(money));
		arrearsService.updateById(arrears);

//		BlSubExpenses subExpenses = blSubExpensesService.getById(subExpenseId);

//		subExpenses.setDerateMoney(money);
//		subExpenses.setMoney(subExpenses.getMoney().subtract(money));
//		blSubExpensesService.updateById(subExpenses);

		chgDerate.setNewMoney(arrears.getMoney());

//		BlExpenses expenses = blExpensesService.getById(expenseId);
//		expenses.setDerateMoney(expenses.getDerateMoney().add(money));
//		expenses.setMoney(expenses.getMoney().subtract(money));
//		blExpensesService.updateById(expenses);

		chgDerate.setArrearsId(arrearId);
//		chgDerate.setExpenseId(expenseId);
//		chgDerate.setSubExpenseId(subExpenseId);
		chgDerate.setFeeStrikeCause(feeStrikeCause);
		chgDerate.setItemCode("02");//违约金

		chgDerate.setResponMan(responMan);
		chgDerate.setRemark(remark+"违约金减免");
		chgDerateService.save(chgDerate);

		///**设置首页数据动态更新*/
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					/**设置首页数据动态更新-费用违约金减免*/
					indexData(null,null);
				} catch (Exception e) {
					e.printStackTrace();
				} finally {
					log.warn("首页数据动态更新");
				}
			}
		}).start();

		return Result.OK("减免成功");
	}

	/**按水表用户分组的收费记录*/
	public JSONObject getFeeListByPayments(String paymentId){
		//用户收费对应ID 过滤已开票据的
		JSONObject userFeeIdJson = new JSONObject();

		List<ChgFees> feesList = noOpenBillFees(paymentId);
		if(null != feesList && feesList.size()>0){
			for (ChgFees chgFees : feesList) {
				if (!userFeeIdJson.containsKey(chgFees.getCusId())) {
					JSONArray jsonArray = new JSONArray();
					jsonArray.add(chgFees.getId());
					userFeeIdJson.put(chgFees.getCusId(), jsonArray);
				} else {
					userFeeIdJson.getJSONArray(chgFees.getCusId()).add(chgFees.getId());
				}
			}
		}
		return userFeeIdJson;
	}

	/**收费汇总*/
	@Override
	public List<ChgFeeCountVo> chargeFeeCount( String beginDate,String endDate){
		return chgFeesMapper.chargeFeeCount(beginDate,endDate);
	}


	//批次号
	public String createBatchNo(){
		SimpleDateFormat format = new SimpleDateFormat("yyMMddHHmmss");
		int random = RandomUtils.nextInt(90) + 10;
		String value = format.format(new Date()) + random;
		return value;
	}
}
